JAVA集合源码解析 HashSet 探索(基于JDK1.8)

JDK1.8HashSet探索

本文所讨论的源码是基于JDK1.8展开的,由于篇幅有限,只讨论主要部分

1.简介

HashSet 是不同步的,继承的 set 接口,所以里面的元素是不能重复的,无序的,允许包含值为null的元素,但最多只能有一个null元素。很多内部实现是基于 HashMap 的,可以看成是一个 HashMap 的简单封装,分析过 HashMap ,这个进度就会快很多。

2.探索

2.1类关系

HashSet

  1. HashSet 继承了 AbstractSet 类,这个类也实现了 Set 方法。
  2. HashSet 实现了 Serializable ,能进行序列化操作。
  3. HashSet 实现了Set 接口,能够实现其中的 Set 集合中的一些操作。
  4. HashSet 实现了 Cloneable 接口,能够使用 clone() 方法。

2.2属性

    // Map
    private transient HashMap<E,Object> map;

    // 用作所有键对应的值,键所对应的值都相等
    private static final Object PRESENT = new Object();

属性比较少,都是一目了然的

2.3构造方法

    /**
     * 构造一个新的空集; HashMap
     * 默认初始容量(16)和负载系数(0.75)
     */
    public HashSet() {
        map = new HashMap<>();
    }

    /**
     * 构造一个包含指定元素的新集合
     */
    public HashSet(Collection<? extends E> c) {
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));//调用的是hashMap的初始化
        addAll(c);
    }

    /**
     * 构造一个新的空集; 背后 HashMap 实例具有指定的初始容量和指定的加载因子。
     *
     */
    public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }

    /**
     * 构造一个新的空集; HashMap 实例具有
       指定的初始容量和默认加载因子(0.75)。
     *
     */
    public HashSet(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }

    /**
     * 构造一个新的空链接哈希集(此私有构造函数仅由LinkedHashSet使用。)
     * 支持HashMap实例是具有指定的初始容量和指定的加载因子的LinkedHashMap。
     *
     */
    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }
  1. 前面 4 个构造方法都是基于 HashMap 来提供底层支持的。
  2. HashSet(int initialCapacity, float loadFactor, boolean dummy) 带3个参数的构造函数底层是 LinkedHashMap 实现的。(虽然LinkedHashMap也是一个HashMap,233333)

2.4核心方法

(1)add(E e)

    /**
     * 如果指定的元素不存在,则将其添加到此集合中。
     *
     */
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

(2)remove(Object o)

    /**
     * 如果存在,则从该集合中删除指定的元素。
     *
     */
    public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

(3)clear()

    /**
     * 删除此组中的所有元素。
     */
    public void clear() {
        map.clear();
    }

底层都是调用 HashMap来实现,之前介绍过,这里就不在赘述,想了解的小伙伴可以看这里HashMap探索

3.总结

  1. 这个类实现了Set接口,(实际上是一个HashMap实例)。
  2. 它不能保证集合的中元素的顺序;特别是它并不能保证订单将保持不变。
  3. 这个类允许包含值为null的元素.
  4. HashSet不是同步的。如果多个线程同时访问一个哈希集合,并且至少有一个线程修改集合,它必须在外部同步。
    对该集合的非同步访问可以使用:
    s = Collections.synchronizedSet(new HashSet(…));

猜你喜欢

转载自blog.csdn.net/ouzhuangzhuang/article/details/80257686