有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java内部HashSet只使用HashMap,但为什么我们选择HashSet而不是HashMap呢?

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;
    }
 }

HashSet内部只使用HashMap,性能方面的HashMap比HashSet快 那么为什么我们不直接使用HashMap而不是HashSet呢


共 (2) 个答案

  1. # 1 楼答案

    @m.antkowicz指出,尽管它在内部使用HashMap,但不能保证

    另一个主要原因:

    1. 通常在大型项目中,接口的定义独立于实现
    2. 如果业务接口需要集合(甚至集合),它会将其定义为Set(或Collection
    3. 接口不关心底层的实现(它们假定预期的行为将得到维护)
    4. 接口的任何具体业务实现都应该准确地声明方法签名(以覆盖)
    5. 因此,他们也会使用Set(或Collection

    而且,不同的Set实现使用不同的Map

    1. ConcurrentSkipListSet使用ConcurrentNavigableMap
    2. HashSet使用HashMap

    因此,这很难在接口合同中准确使用

  2. # 2 楼答案

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

    HashMap<MyItem, Object> set;
    

    然后,不要使用set.add(new MyItem())之类的东西,而是使用set.put(new MyItem(), null)这样的东西,它毫无意义,可能会导致严重的问题(当Object的类型将被更改时,当您需要序列化时等等)

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

    What is the difference between Lists, ArrayLists, Maps, Hashmaps, Collections etc..?