Java HashSet内部只使用HashMap,但是为什么我们要使用HashSet而不是HashMap呢?

Java HashSet内部只使用HashMap,但是为什么我们要使用HashSet而不是HashMap呢?,java,dictionary,collections,hashmap,hashset,Java,Dictionary,Collections,Hashmap,Hashset,HashSet的内部实现 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable { private transient HashMap<E,Object> map; private static final Object PRESENT = new Object(); //construc

HashSet的内部实现

public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
   private transient HashMap<E,Object> map;
   private static final Object PRESENT = new Object();
   //constructors
   public HashSet() {
    map = new HashMap<>();
   }
   public HashSet(int initialCapacity) {
    map = new HashMap<>(initialCapacity);
   }
   public HashSet(int initialCapacity, float loadFactor) {
    map = new HashMap<>(initialCapacity, loadFactor);
   }
   public HashSet(Collection<? usnoextends E> c) {
    map = new HashMap<>(Math.imax((int) (c.size()/.75f) + 1, 16));
    addAll(c);
   }
   //add method
   public boolean add(E e) {
    return map.put(e, PRESENT)==null;
    }
 }
公共类哈希集
扩展抽象集
实现Set、Cloneable、java.io.Serializable
{
私有瞬态HashMap;
私有静态最终对象存在=新对象();
//建设者
公共哈希集(){
map=新的HashMap();
}
公共哈希集(int initialCapacity){
map=新HashMap(初始容量);
}
公共哈希集(int initialCapacity,float loadFactor){
map=新的HashMap(初始容量、负载因子);
}

公共HashSet(Collection,因为
HashSet
是另一种类型的集合-集中于单个对象而不是一对项。要使
HashMap
HashSet
一样工作,我们需要在任何地方提供一些类似于

HashMap<MyItem, Object> set;
HashMap集;
然后使用类似于
set.put(new MyItem(),null)
的方法来代替例如
set.add(new MyItem())
什么没有意义并且可能导致严重问题(当
对象的类型发生变化时,当您需要序列化时等等)

此外,内部实现是不需要注意的-它可以在下一个Java版本中更改(可能不会更改),下面将使用另一种机制。最重要的是
Set
接口,事实上
HashSet
正在实现它


因为
HashSet
是另一种类型的集合-集中于单个对象而不是一对项。要使
HashMap
HashSet
一样工作,我们需要在任何地方提供一些类似于

HashMap<MyItem, Object> set;
HashMap集;
然后使用类似于
set.put(new MyItem(),null)
的方法来代替例如
set.add(new MyItem())
什么没有意义并且可能导致严重问题(当
对象的类型发生变化时,当您需要序列化时等等)

此外,内部实现是不需要注意的-它可以在下一个Java版本中更改(可能不会更改),下面将使用另一种机制。最重要的是
Set
接口,事实上
HashSet
正在实现它


正如@m.antkowicz所指出的,尽管它在内部使用HashMap,但无法保证

另一个主要原因是:

  • 通常在大型项目中,接口的定义独立于实现
  • 如果业务接口需要Set(甚至是Collection),它会将其定义为
    Set
    (或
    Collection
  • 接口不关心底层实现(它们假定将保持预期的行为)
  • 接口的任何业务具体实现都应该准确地声明方法签名(以覆盖)
  • 因此,他们还将使用
    Set
    (或
    Collection
  • 另外,
    Set
    的不同实现使用不同的
    Map

  • ConcurrentSkipListSet
    使用
    ConcurrentNavigableMap
  • HashSet
    使用
    HashMap

  • 因此,很难在接口契约中准确地使用它。

    正如@m.antkowicz所指出的,尽管它在内部使用HashMap,但无法保证

    另一个主要原因是:

  • 通常在大型项目中,接口的定义独立于实现
  • 如果业务接口需要Set(甚至是Collection),它会将其定义为
    Set
    (或
    Collection
  • 接口不关心底层实现(它们假定将保持预期的行为)
  • 接口的任何业务具体实现都应该准确地声明方法签名(以覆盖)
  • 因此,他们还将使用
    Set
    (或
    Collection
  • 另外,
    Set
    的不同实现使用不同的
    Map

  • ConcurrentSkipListSet
    使用
    ConcurrentNavigableMap
  • HashSet
    使用
    HashMap

  • 因此,在接口契约中很难准确地使用它。

    在某些情况下,您可能希望使用集合而不是hashmap。您确切的问题是什么?您所说的“性能方面的hashmap比HashSet快”是什么意思?在某些情况下,您可能希望使用集合而不是hashmap。您确切的问题是什么?您所说的“性能方面的hashmap比HashSet快”是什么意思?