java集合-HashSet源码解析

HashSet 无序集合类

  • 实现了Set接口
  • 内部通过HashMap实现
// HashSet
public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
{
    static final long serialVersionUID = -5024744406713321676L;

    //重要:HashMap HashSet就是通过HashMap保存数据, HashSet的值就是HashMap的key
    private transient HashMap<E,Object> map;  // 使用transient修饰不会被序列化
    
    //HashMap 为<key, value>的键值对, 既然HashSet的值就是HashMap的key, 那么HashMap的值呢,当然就是这个PRESENT,HashMap所有的value都是同一个对象
    private static final Object PRESENT = new Object();
    
    // 默认构造函数,创建一个HashMap对象
    public HashSet() {
        map = new HashMap<>();
    }

    //将一个已知的collection转换为HashSet
    public HashSet(Collection<? extends E> c) {
        //Collection<? extends E> c 限制了类型上限为E,也就是c只能是E类型或E的子类,防止参数是非Set类型
        //如果没有指定HashMap的capacity, 那么默认的就是16
        //根据 threshold = capacity * loadFactor, 可以计算出 capacity
        //Math.max((int) (c.size()/.75f) + 1, 16) 这个意思就是capacity如果没超过16, 那么就直接使用默认的16
        // 容量设置为4/3倍
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        //将已知的collection转换为HashSet的方法
        //addAll方法是HashSet的父类AbstractCollection的方法,为了便于阅读,会将代码粘贴在下面
        addAll(c);
    }
    // 带有初始容量和因子的构造函数
    public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }


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


    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }
    
    //addAll方法是HashSet的父类AbstractCollection的方法
    public boolean addAll(Collection<? extends E> c) {
        boolean modified = false; // 只要添加了元素就返回true
        for (E e : c)
            //此处的add方法由HashSet重写实现
            if (add(e))
                modified = true;
        return modified;
    }
    
    //HashSet的核心方法来了, 没错,就这么简单
    public boolean add(E e) {
        //应证了上面所说的key为HashSet的值
        return map.put(e, PRESENT)==null;
    }
    
    //剩下这些方法都是跟Map相关的了,只要熟悉了HashMap, 那就太简单了,就不说了
    public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

    public void clear() {
        map.clear();
    }
    
}



补充

泛型

泛型的上限通配符<? extends T>

<? extends T>是 Upper Bound(上限) 的通配符,用来限制元素的类型的上限,比如  

List<? extends Fruit> fruits;  
表示集合中的元素类型上限为Fruit类型,即只能是Fruit或者Fruit的子类。

泛型的下限通配符<? super T>

<? super E> 是 Lower Bound(下限) 的通配符 ,用来限制元素的类型下限,比如

List<? super Apple> apples;  
表示集合中元素类型下限为Apple类型,即只能是Apple或Apple的父类。

参考

原文地址:https://www.cnblogs.com/wang7/p/10146422.html