Set
集合的最主要特性就是没有重复元素,HashSet
是Set的一个字类,其内部基于HashMap实现
1. 成员变量
private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();
可以看到HashSet内部有一个HashMap, 但是PRESENT
是干什么用的?HashMap是key-value形式的,但是Set是存储的是单一值,那么内部想要借由HashMap来实现的话,就必须有一个固定的value值,即HashSet中存放的每一个值在HashMap中作为key值,对应的value值都固定为PRESENT对象
2. 构造函数
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(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
一般起我们最常用的就是空参构造函数,在空参函数中会调用HashMap的空参构造函数, 由HashMap源码分析可以知道,空参构造函数的HashMap初始容量为4
3. 方法
3.1 add
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
在HashMap中,如果key值没有hash碰撞或者在冲突的链表上没有相同的key,HashMap.put会返回null, 否则会返回被替换的旧值,而由于HashSet中,所有key值对应的value都是PRESENT
对象,这样就算在HashMap中有相等的key值,更新的也只是PRESENT
,并没有在HashMap中插入新的key值,从而保证了HashSet
中值的唯一性
3.2 remove
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
HashMap.remove如果删除成功,会返回对应的value,如果不存在对应的entry则返回null, 而HashSet中所有key值对应的value固定都是PRESENT
3.3 iterator
public Iterator<E> iterator() {
return map.keySet().iterator();
}