概览

1
2
3
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable

值得注意的是HashSet底层是基于HashMap来实现的。
HashSet是一个集合,集合是没有重复的元素的,不能保证顺序的。而且HashSet是非同步的。
它的继承体系如下
eWw2hF.png

属性

1
2
3
4
private transient HashMap<E,Object> map;

private static final Object PRESENT = new Object();

上文已经提到HashSet的底层是采用HashMap来实现的,但是只用到了key,它使用一个静态的对象PRESENT来填充value,其实可以使用null来填充value的,因为HashMap是支持空键和空值的。我的猜想这样的设计虽然会浪费一点点内存,但是可以避免出现因为操作失误出现空指针异常。

构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public HashSet() {
map = new HashMap<>();
}

public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}

public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}

public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}

HashSet公开的构造器的主要的工作就是初始化HashMap。这就不赘述了。

方法

eW2IRP.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 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 boolean contains(Object o) {
return map.containsKey(o);
}

public boolean isEmpty() {
return map.isEmpty();
}

public int size() {
return map.size();
}

public Iterator<E> iterator() {
return map.keySet().iterator();
}

这些方法也都是调用HashMap的方法,基本没什么说的,看来HashMap很重要啊。