首页 > 代码库 > Java源码初学_HashSet&LinkedHashSet

Java源码初学_HashSet&LinkedHashSet

一.概述

  HashSet是建立在HashMap的基础上的,其内部存在指向一个HashMap对象的引用,操作HashSet实际上就是操作HashMap,而HashMap中所有键的值都指向一个叫做Dummy value的值.这是一个Object对象.是在HashSet进行显示初始化的时候初始化出来的,而HashMap在构造函数中被创建出来.
二.HashMap在HashSet方法中的使用及LinkedHashMap
  HashSet是建立在HashMap的基础上的,它的几乎所有的操作都是通过HashMap完成对于key的操作来实现的,通过add方法可以得知,这个HashMap所有的键都指向一个值.

public class HashSet<E>    extends AbstractSet<E>    implements Set<E>, Cloneable, java.io.Serializable{    static final long serialVersionUID = -5024744406713321676L;    //存储键值对的Map.这个Map将不会被序列化    private transient HashMap<E,Object> map;    // Dummy value     private static final Object PRESENT = new Object();    public HashSet() {    map = new HashMap<E,Object>();    }    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);    }    //LinkedHashSet的实现关键    HashSet(int initialCapacity, float loadFactor, boolean dummy) {    map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);    }    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);    }    public boolean add(E e) {    //放入元素和present的键值对    return map.put(e, PRESENT)==null;    }    public boolean remove(Object o) {    return map.remove(o)==PRESENT;    }    public void clear() {    map.clear();    }

   有两点需要注意的,第一点,这个Map是不会序列化的,因此在写入文件的时候,除了写入文件HashSet的信息以外,还写入map的容量(capacity),装填因子(loadFactor)以及元素数目(size),然后在从文件读取的时候,先创建map,然后依次从map中装填key的信息.代码如下:

private void writeObject(java.io.ObjectOutputStream s)        throws java.io.IOException {    s.defaultWriteObject();        s.writeInt(map.capacity());        s.writeFloat(map.loadFactor());        s.writeInt(map.size());    for (Iterator i=map.keySet().iterator(); i.hasNext(); )            s.writeObject(i.next());    }    private void readObject(java.io.ObjectInputStream s)        throws java.io.IOException, ClassNotFoundException {    s.defaultReadObject();        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));        int size = s.readInt();    for (int i=0; i<size; i++) {            E e = (E) s.readObject();            map.put(e, PRESENT);        }    }

    第二点,HashSet中有一个不是公共的有boolean类型的参数的构造方法,它供LinkedHashSet调用.可以将LinkedHashSet内置的Map引用初始化为LinkedHashMap对象.(注意LinkedHashSet无法实现按照访问顺序排序).

Java源码初学_HashSet&LinkedHashSet