1 packagejava.util;2
3 public class HashSet
4 extends AbstractSet
5 implements Set, Cloneable, java.io.Serializable6 {7 static final long serialVersionUID = -5024744406713321676L;8
9 //HashSet是通过map(HashMap对象)保存内容的
10 private transient HashMapmap;11
12 //PRESENT是向map中插入key-value对应的value13 //因为HashSet中只需要用到key,而HashMap是key-value键值对;14 //所以,向map中添加键值对时,键值对的值固定是PRESENT
15 private static final Object PRESENT = newObject();16
17 //默认构造函数
18 publicHashSet() {19 //调用HashMap的默认构造函数,创建map
20 map = new HashMap();21 }22
23 //带集合的构造函数
24 public HashSet(Collection extends E>c) {25 //创建map。26 //为什么要调用Math.max((int) (c.size()/.75f) + 1, 16),从 (c.size()/.75f) + 1 和 16 中选择一个比较大的树呢?27 //首先,说明(c.size()/.75f) + 128 //因为从HashMap的效率(时间成本和空间成本)考虑,HashMap的加载因子是0.75。29 //当HashMap的“阈值”(阈值=HashMap总的大小*加载因子) < “HashMap实际大小”时,30 //就需要将HashMap的容量翻倍。31 //所以,(c.size()/.75f) + 1 计算出来的正好是总的空间大小。32 //接下来,说明为什么是 16 。33 //HashMap的总的大小,必须是2的指数倍。若创建HashMap时,指定的大小不是2的指数倍;34 //HashMap的构造函数中也会重新计算,找出比“指定大小”大的最小的2的指数倍的数。35 //所以,这里指定为16是从性能考虑。避免重复计算。
36 map = new HashMap(Math.max((int) (c.size()/.75f) + 1, 16));37 //将集合(c)中的全部元素添加到HashSet中
38 addAll(c);39 }40
41 //指定HashSet初始容量和加载因子的构造函数
42 public HashSet(int initialCapacity, floatloadFactor) {43 map = new HashMap(initialCapacity, loadFactor);44 }45
46 //指定HashSet初始容量的构造函数
47 public HashSet(intinitialCapacity) {48 map = new HashMap(initialCapacity);49 }50
51 HashSet(int initialCapacity, float loadFactor, booleandummy) {52 map = new LinkedHashMap(initialCapacity, loadFactor);53 }54
55 //返回HashSet的迭代器
56 public Iteratoriterator() {57 //实际上返回的是HashMap的“key集合的迭代器”
58 returnmap.keySet().iterator();59 }60
61 public intsize() {62 returnmap.size();63 }64
65 public booleanisEmpty() {66 returnmap.isEmpty();67 }68
69 public booleancontains(Object o) {70 returnmap.containsKey(o);71 }72
73 //将元素(e)添加到HashSet中
74 public booleanadd(E e) {75 return map.put(e, PRESENT)==null;76 }77
78 //删除HashSet中的元素(o)
79 public booleanremove(Object o) {80 return map.remove(o)==PRESENT;81 }82
83 public voidclear() {84 map.clear();85 }86
87 //克隆一个HashSet,并返回Object对象
88 publicObject clone() {89 try{90 HashSet newSet = (HashSet) super.clone();91 newSet.map = (HashMap) map.clone();92 returnnewSet;93 } catch(CloneNotSupportedException e) {94 throw newInternalError();95 }96 }97
98 //java.io.Serializable的写入函数99 //将HashSet的“总的容量,加载因子,实际容量,所有的元素”都写入到输出流中
100 private voidwriteObject(java.io.ObjectOutputStream s)101 throwsjava.io.IOException {102 //Write out any hidden serialization magic
103 s.defaultWriteObject();104
105 //Write out HashMap capacity and load factor
106 s.writeInt(map.capacity());107 s.writeFloat(map.loadFactor());108
109 //Write out size
110 s.writeInt(map.size());111
112 //Write out all elements in the proper order.
113 for (Iterator i=map.keySet().iterator(); i.hasNext(); )114 s.writeObject(i.next());115 }116
117
118 //java.io.Serializable的读取函数119 //将HashSet的“总的容量,加载因子,实际容量,所有的元素”依次读出
120 private voidreadObject(java.io.ObjectInputStream s)121 throwsjava.io.IOException, ClassNotFoundException {122 //Read in any hidden serialization magic
123 s.defaultReadObject();124
125 //Read in HashMap capacity and load factor and create backing HashMap
126 int capacity =s.readInt();127 float loadFactor =s.readFloat();128 map = (((HashSet)this) instanceof LinkedHashSet ?
129 new LinkedHashMap(capacity, loadFactor) :130 new HashMap(capacity, loadFactor));131
132 //Read in size
133 int size =s.readInt();134
135 //Read in all elements in the proper order.
136 for (int i=0; i