// 底层使用HashMap来保存HashSet的元素
private transient HashMap<E,Object> map;
// Set使用的只是Map的Key,所以这里定义一个静态常量充当value
private static final Object PRESENT = new Object();
关于value的使用:为什么不用null?
因为HashSet中的很多方法都是依赖HashMap实现,而这些方法需要通过返回null来判断是否执行成功,如果value使用null,那么就无法分清方法返回的null的真正含义了
public HashSet() {
map = new HashMap<>();
}
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
// 调用AbstractCollection中的方法遍历添加集合元素
addAll(c);
}
// 该方法是AbstractCollection默认实现的
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
/*该方法不对外公开,实际上是提供给LinkedHashSet使用的,而第三个参数dummy是无意义的,只是为了区分其他构造方法。 */
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
public boolean contains(Object o) {
return map.containsKey(o);
}
public void clear() {
map.clear();
}
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
博客推荐:TreeSet源码分析-java8
LinkedHashSet继承自HashSet,但是是基于LinkedHashMap实现的(前面说过它调用的是HashSet中不公开的构造函数,构建了一个LinkedHashSet)