package java.util;
// HashSet继承了AbstractSet,实现了Set、Cloneable和java.io.Serializable接口
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
// 序列化版本号
static final long serialVersionUID = -5024744406713321676L;
// 不可被默认序列化的HashMap引用
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
// 与后台映射中的对象关联的虚拟值
private static final Object PRESENT = new Object();
1 /**
2 * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
3 * default initial capacity (16) and load factor (0.75).
4 */
5 // 无参构造方法
6 public HashSet() {
7 map = new HashMap<>();
8 }
// 初始容量和负载因子作为参数的构造方法
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
// 初始容量作为参数的构造方法
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
// 初始容量、负载因子和布尔类型值作为参数的构造方法,与前面不同的是创建了LinkedHashMap对象
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(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);
}
1 // 添加元素 2 // 元素重复时会覆盖但内容相同 3 // 如果put方法调用的putVal方法返回null,说明原来没有该key 4 public boolean add(E e) { 5 return map.put(e, PRESENT)==null; 6 }
// 删除元素
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
// 清空集合
public void clear() {
map.clear();
}
1 /**
2 * Returns a shallow copy of this <tt>HashSet</tt> instance: the elements
3 * themselves are not cloned.
4 *
5 * @return a shallow copy of this set
6 */
7 // 克隆,浅复制
8 @SuppressWarnings("unchecked")
9 public Object clone() {
10 try {
11 HashSet<E> newSet = (HashSet<E>) super.clone();
12 newSet.map = (HashMap<E, Object>) map.clone();
13 return newSet;
14 } catch (CloneNotSupportedException e) {
15 throw new InternalError(e);
16 }
17 }
1 /**
2 * Save the state of this <tt>HashSet</tt> instance to a stream (that is,
3 * serialize it).
4 *
5 * @serialData The capacity of the backing <tt>HashMap</tt> instance
6 * (int), and its load factor (float) are emitted, followed by
7 * the size of the set (the number of elements it contains)
8 * (int), followed by all of its elements (each an Object) in
9 * no particular order.
10 */
11 // 序列化
12 private void writeObject(java.io.ObjectOutputStream s)
13 throws java.io.IOException {
14 // Write out any hidden serialization magic
15 s.defaultWriteObject();
16
17 // Write out HashMap capacity and load factor
18 s.writeInt(map.capacity());
19 s.writeFloat(map.loadFactor());
20
21 // Write out size
22 s.writeInt(map.size());
23
24 // Write out all elements in the proper order.
25 for (E e : map.keySet())
26 s.writeObject(e);
27 }
1 /**
2 * Reconstitute the <tt>HashSet</tt> instance from a stream (that is,
3 * deserialize it).
4 */
5 // 反序列化
6 private void readObject(java.io.ObjectInputStream s)
7 throws java.io.IOException, ClassNotFoundException {
8 // Read in any hidden serialization magic
9 s.defaultReadObject();
10
11 // Read capacity and verify non-negative.
12 int capacity = s.readInt();
13 if (capacity < 0) {
14 throw new InvalidObjectException("Illegal capacity: " +
15 capacity);
16 }
17
18 // Read load factor and verify positive and non NaN.
19 float loadFactor = s.readFloat();
20 if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
21 throw new InvalidObjectException("Illegal load factor: " +
22 loadFactor);
23 }
24
25 // Read size and verify non-negative.
26 int size = s.readInt();
27 if (size < 0) {
28 throw new InvalidObjectException("Illegal size: " +
29 size);
30 }
31
32 // Set the capacity according to the size and load factor ensuring that
33 // the HashMap is at least 25% full but clamping to maximum capacity.
34 capacity = (int) Math.min(size * Math.min(1 / loadFactor, 4.0f),
35 HashMap.MAXIMUM_CAPACITY);
36
37 // Create backing HashMap
38 map = (((HashSet<?>)this) instanceof LinkedHashSet ?
39 new LinkedHashMap<E,Object>(capacity, loadFactor) :
40 new HashMap<E,Object>(capacity, loadFactor));
41
42 // Read in all elements in the proper order.
43 for (int i=0; i<size; i++) {
44 @SuppressWarnings("unchecked")
45 E e = (E) s.readObject();
46 map.put(e, PRESENT);
47 }
48 }