java容器 类HashSet源码分析

目录

简介

字段 map,PRESENT

构造函数5个

查询  iterator,size,isEmpty,contains

操作 add,remove,clear

clone,readObject,writeObject

spliterator


简介

/**
 * 这个类实现Set接口,由一个散列表(实际上是一个HashMap实例)支持。
 * 它不保证集合的迭代顺序;特别是,它不能保证顺序保持不变。该类允许null元素。
 *
 * 

这个类为基本操作(add,remove,contains,size)提供了常数时间性能,假设散列函数正确地将元素分散到各个桶中。 * 遍历这个集合需要的时间与HashSet实例的大小(元素的数量) 加上 支持HashMap实例的“容量”(桶的数量)的总和成比例。 * 因此,如果迭代性能很重要,那么不要将初始容量设置得太高(或负载因子太低)是非常重要的。 * *

注意,这个实现不是同步的。如果多个线程同时访问一个散列集, * 并且至少有一个线程修改该散列集,则必须在外部对其进行同步。 * 这通常是通过对一些自然封装了集合的对象进行同步来实现的。 * * 如果不存在这样的对象,则应该使用Collections.synchronizedSet方法来保证它。 * 这最好在创建时完成,以防止意外的不同步的访问set的行为: * *

 *   Set s = Collections.synchronizedSet(new HashSet(...));
* *

这个类的迭代器方法返回的迭代器是快速失效的:如果在迭代器创建后的任何时候修改集合, * 除了通过迭代器自己的删除方法之外,任何方式都可以,迭代器抛出ConcurrentModificationException。 * 因此,在面对并发修改时,迭代器会快速而干净地失败,而不是在将来某个不确定的时间冒任意的、不确定的行为的风险。 * *

注意,不能保证迭代器的快速故障行为,因为通常来说,在存在非同步并发修改的情况下,不可能做出任何严格的保证。 * 故障快速迭代器在最大努力的基础上抛出ConcurrentModificationException。 * 因此,编写一个依赖于这个异常的正确性的程序是错误的:迭代器的快速故障行为应该只用于检测bug。 * * @param the type of elements maintained by this set * * @author Josh Bloch * @author Neal Gafter * @see Collection * @see Set * @see TreeSet * @see HashMap * @since 1.2 */ public class HashSet extends AbstractSet implements Set, Cloneable, java.io.Serializable

java容器 类HashSet源码分析_第1张图片

字段 map,PRESENT

    // 内置了一个map
    private transient HashMap map;

    // map.put(e, PRESENT) 作为map里的value
    // PRESENT是static final的常量,所有hashset共享
    private static final Object PRESENT = new Object();

构造函数5个

    /**
     * 创建一个新的,空的set,依赖的HashMap实例是默认的,初始容量为16,初始负载因子为0.75
     */
    public HashSet() {
        map = new HashMap<>();
    }

    /**
     * 构造一个新集合,该集合包含指定集合中的元素。
     * HashMap是使用默认的负载因子(0.75)和足够容纳指定集合中的元素的初始容量创建的。
     *
     * @param c the collection whose elements are to be placed into this set
     * @throws NullPointerException if the specified collection is null
     */
    public HashSet(Collection c) {
    	// c的size/0.75 +1 为容量  ,最小为16
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
    }

    /**
     * 构造一个新的空集;支持的HashMap实例具有指定的初始容量和指定的负载因子。
     * 
     * @param      initialCapacity   the initial capacity of the hash map
     * @param      loadFactor        the load factor of the hash map
     * @throws     IllegalArgumentException if the initial capacity is less
     *             than zero, or if the load factor is nonpositive
     */
    public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }

    /**
     * 构造一个新的空集;支持的HashMap实例具有指定的初始容量和缺省负载因子(0.75)。
     *
     * @param      initialCapacity   the initial capacity of the hash table
     * @throws     IllegalArgumentException if the initial capacity is less
     *             than zero
     */
    public HashSet(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }

    /**
     * 构造一个新的空的链接哈希集(这个包的私有构造函数只被LinkedHashSet使用)。
     * 支持的HashMap实例是一个LinkedHashMap,它具有指定的初始容量和指定的负载因子。
     *
     * @param      initialCapacity   the initial capacity of the hash map
     * @param      loadFactor        the load factor of the hash map
     * @param      dummy             ignored (distinguishes this
     *             constructor from other int, float constructor.)
     * @throws     IllegalArgumentException if the initial capacity is less
     *             than zero, or if the load factor is nonpositive
     */
    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }

查询  iterator,size,isEmpty,contains

    /**
     * 在这个集合的元素上返回一个迭代器。元素没有按照特定的顺序返回。
     *
     * @return an Iterator over the elements in this set
     * @see ConcurrentModificationException
     */
    public Iterator iterator() {
    	// 返回map的keySet视图的迭代器
        return map.keySet().iterator();
    }

    /**
     * 返回此集合中的元素
     *
     * @return the number of elements in this set (its cardinality)
     */
    public int size() {
        return map.size();
    }

    /**
     * 如果该集合不包含元素,则返回true。
     *
     * @return true if this set contains no elements
     */
    public boolean isEmpty() {
        return map.isEmpty();
    }

    /**
     * 如果set包含指定元素,返回true。
     * 更正式地,当且仅当集合至少有一个这样的元素时,返回true。
     * (o==null ? e==null : o.equals(e)).
     *
     * @param o element whose presence in this set is to be tested
     * @return true if this set contains the specified element
     */
    public boolean contains(Object o) {
    	// map是否有这个key
        return map.containsKey(o);
    }

操作 add,remove,clear

    /**
     * 

如果set没有指定元素,将指定元素加入set。 * 更正式地说,如果set不包含元素e2,有指定元素e, * (e==null ? e2==null : e.equals(e2)) * 将e加入到set。 * *

如果set已经包含了这个元素,调用让set不改变,并且返回false。 * * @param e element to be added to this set * @return true if this set did not already contain the specified * element */ public boolean add(E e) { // key为e,value为一个常量 new Object() return map.put(e, PRESENT)==null; } /** * 如果指定元素存在,从set中移除指定元素(可选的操作)。 * 更正式地说,如果set包含一个这样的元素,就移除一个这样的元素 , * (o==null ? e==null : o.equals(e)) * 如果集合包含指定元素,返回true。(如果集合因为调用而改变,返回true) * (调用结束后,set不会包含这个元素) * * @param o object to be removed from this set, if present * @return true if the set contained the specified element */ public boolean remove(Object o) { // map移除key为o return map.remove(o)==PRESENT; } /** * 移除set中所有的元素 */ public void clear() { map.clear(); }

clone,readObject,writeObject

    /**
     * 返回此HashSet实例的浅拷贝:元素本身没有被克隆。
     *
     * @return a shallow copy of this set
     */
    @SuppressWarnings("unchecked")
    public Object clone() {
        try {
        	// 对自己进行浅拷贝
            HashSet newSet = (HashSet) super.clone();
            // 对map进行浅拷贝
            newSet.map = (HashMap) map.clone();
            return newSet;
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }

    /**
     * 将这个HashSet实例的状态保存到流中(即序列化它)。
     *
     * @serialData The capacity of the backing HashMap instance
     *             (int), and its load factor (float) are emitted, followed by
     *             the size of the set (the number of elements it contains)
     *             (int), followed by all of its elements (each an Object) in
     *             no particular order.
     */
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
        // 写出隐藏的字段。
        s.defaultWriteObject();

        // 写出HashMap的容量和负载因子
        s.writeInt(map.capacity());
        s.writeFloat(map.loadFactor());

        // 写出size
        s.writeInt(map.size());

        // 以适当的顺序写出所有的元素
        for (E e : map.keySet())
            s.writeObject(e);
    }

    /**
     * 从流中重新构造HashSet实例(即反序列化它)。
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        // 读入隐藏字段
        s.defaultReadObject();

        // 读入容量,验证非负
        int capacity = s.readInt();
        if (capacity < 0) {
            throw new InvalidObjectException("Illegal capacity: " +
                                             capacity);
        }

        // 读入负载因子,验证整数和不是NaN
        float loadFactor = s.readFloat();
        if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
            throw new InvalidObjectException("Illegal load factor: " +
                                             loadFactor);
        }

        // 读入size,验证非负
        int size = s.readInt();
        if (size < 0) {
            throw new InvalidObjectException("Illegal size: " +
                                             size);
        }

        // 根据size和负载因子,设置容量,保证HashMap至少是25%是满的,但是小于最大容量
        capacity = (int) Math.min(size * Math.min(1 / loadFactor, 4.0f),
                HashMap.MAXIMUM_CAPACITY);

        // 创建支持的HashMap,安装上面得到的capacity和loadFactor
        // 根据自己是HashSet还是LinkedHashSet,创建HashMap,LinkedHashMap
        map = (((HashSet)this) instanceof LinkedHashSet ?
               new LinkedHashMap(capacity, loadFactor) :
               new HashMap(capacity, loadFactor));

        // 以适当的顺序读入所有的元素
        for (int i=0; i

spliterator

    /**
     * 在这个集合的元素上创建一个迟绑定和快速失败的Spliterator。
	 * Spliterator报告SIZED和DISTINCT。覆盖的实现应该记录额外特征值。
     *
     * @return a {@code Spliterator} over the elements in this set
     * @since 1.8
     */
    public Spliterator spliterator() {
    	// 返回HashMap的keySpliterator
        return new HashMap.KeySpliterator(map, 0, -1, 0, 0);
    }

你可能感兴趣的:(源码分析,java容器)