HashSet源码解析(JDK1.8)

HashSet源码解析(JDK1.8)

HashSet是一个数组+链表(或者红黑树)实现不允许有重复元素的散列表

同样我们还是先上类的关系图

HashSet类的关系图

从类的关系图中可以看出HashSet继承一个抽象类和实现了三个接口,然后分别简单介绍一下:

  • AbstractSet:这里主要提供iterator的相关操作
  • Set:提供增删改查等操作
  • Cloneable:按字段复制操作
  • Serializable:启用其序列化功能操作

属性

属性相关的源码


    private transient HashMap<E,Object> map;

    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();

复制代码

private transient HashMap<E,Object> map;//存储元素的结构直接用的HashMap

private static final Object PRESENT = new Object();//每个存储在HashMap中Value的虚拟值

构造方法

    public HashSet() {
        map = new HashMap<>();
    }

    public HashSet(Collection<? extends E> c) {
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
    }

    public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }

    public HashSet(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }

    //default访问权限,不允许使用者直接调用,是提供给LinkedHashSet使用的
    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }

复制代码

从四个构造方法中可以看出主要是initialCapacity、loadFactor这两个的不同参数,完全对应HashMap的构造方法

initialCapacity:初始容量,默认值采用的是HashMap的默认值16

loadFactor:负载因子,默认值采用的是0.75

增删改查

插入元素


    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
    
复制代码

其实就是调用的HashMap的put方法,然后value值是PRESENT,具体的put执行可参考HashMap的分析

删除元素


    public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

复制代码

其实就是调用的HashMap的remove方法,然后返回值判断一下是否是PRESENT,具体的remove执行可参考HashMap的分析

其他方法

contains()、clear()这些都是直接调用的HashMap想对应的方法。由此可以看出HashSet其实就是用HashMap去实现的,只不过value值都是PRESENT,然后保证了key的唯一性,所以也就是一个不允许有重复元素的散列表

相关对比

  • HashSet也是和HashMap一样是线程不安全的

  • LinkedHashSet是继承HashSet,但是是通过LinkedHashMap去实现的

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享