HashSet源码粗略解析

来源:互联网 发布:java开发月薪 编辑:程序博客网 时间:2024/06/05 05:11

复习下java的常用集合框架,java常用的集合大致有两种类型,一种实现了Collection接口表示普通的集合,一种实现了Map接口表示严格的键值对,其中Collection又分为List接口类型和Set接口类型,其中List接口类型允许集合中元素重复,例如ArrayList,Vector,LinkedList,Stack,Set接口实现的集合不允许重复元素,例如HashSet和TreeSet。

HashSet从类名就可以看出,它使用HashMap的存储方法存储元素,其中也就使用了HashMap的key那一部分,value默认为Object,所以它的元素不会重复。

package java.util;public class HashSet<E>    extends AbstractSet<E>    implements Set<E>, Cloneable, java.io.Serializable{    static final long serialVersionUID = -5024744406713321676L;//存储元素的内部集合    private transient HashMap<E,Object> map;    //因为它只需要保存不重复的key元素,value元素默认为一个Object就好    private static final Object PRESENT = new Object();    /**     * 无参构造函数,默认的容量16,加载因子为3/4     */    public HashSet() {        map = new HashMap<E,Object>();    }    /**     * 略,Math.max是求最大值,找到一个容量的参数,要么是c集合已有个数除以0.75,要么是16     */    public HashSet(Collection<? extends E> c) {        map = new HashMap<E,Object>(Math.max((int) (c.size()/.75f) + 1, 16));        addAll(c);    }    /**     * 略     */    public HashSet(int initialCapacity, float loadFactor) {        map = new HashMap<E,Object>(initialCapacity, loadFactor);    }    /**     * 略     */    public HashSet(int initialCapacity) {        map = new HashMap<E,Object>(initialCapacity);    }    /**     * 参考了他人的说法: 以指定的initialCapacity和loadFactor构造一个新的空链接哈希集合。      * 此构造函数为包访问权限,不对外公开,实际只是是对LinkedHashSet的支持。       * 实际底层会以指定的参数构造一个空LinkedHashMap实例来实现。     */    HashSet(int initialCapacity, float loadFactor, boolean dummy) {        map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);    }    /**     * 返回迭代器,使用的键Set视图集合返回的迭代器     */    public Iterator<E> iterator() {        return map.keySet().iterator();    }    /**     *返回有多少个元素     */    public int size() {        return map.size();    }    /**     * 判断是否为空     */    public boolean isEmpty() {        return map.isEmpty();    }    /**     * 包含     */    public boolean contains(Object o) {        return map.containsKey(o);    }    /**     * 增加一个元素,增加在key的位置上     */    public boolean add(E e) {        return map.put(e, PRESENT)==null;    }    /**     * 删除     */    public boolean remove(Object o) {        return map.remove(o)==PRESENT;    }    /**     * 删除所有     */    public void clear() {        map.clear();    }    /**     * 克隆,调用的底层克隆方法     */    public Object clone() {        try {            HashSet<E> newSet = (HashSet<E>) super.clone();            newSet.map = (HashMap<E, Object>) map.clone();            return newSet;        } catch (CloneNotSupportedException e) {            throw new InternalError();        }    }    /**     * Save the state of this <tt>HashSet</tt> instance to a stream (that is,     * serialize it).     *     * @serialData The capacity of the backing <tt>HashMap</tt> 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 {        // Write out any hidden serialization magic        s.defaultWriteObject();        // Write out HashMap capacity and load factor        s.writeInt(map.capacity());        s.writeFloat(map.loadFactor());        // Write out size        s.writeInt(map.size());        // Write out all elements in the proper order.        for (Iterator i=map.keySet().iterator(); i.hasNext(); )            s.writeObject(i.next());    }    /**     * Reconstitute the <tt>HashSet</tt> instance from a stream (that is,     * deserialize it).     */    private void readObject(java.io.ObjectInputStream s)        throws java.io.IOException, ClassNotFoundException {        // Read in any hidden serialization magic        s.defaultReadObject();        // Read in HashMap capacity and load factor and create backing HashMap        int capacity = s.readInt();        float loadFactor = s.readFloat();        map = (((HashSet)this) instanceof LinkedHashSet ?               new LinkedHashMap<E,Object>(capacity, loadFactor) :               new HashMap<E,Object>(capacity, loadFactor));        // Read in size        int size = s.readInt();        // Read in all elements in the proper order.        for (int i=0; i<size; i++) {            E e = (E) s.readObject();            map.put(e, PRESENT);        }    }}

可以看出HashSet非常简单,非线程安全,向HashMap一样没有容量限制

0 0
原创粉丝点击