关于HashMap的源码解读,可参考https://blog.csdn.net/jiang_zf/article/details/104532186
一、一些变量介绍
//用来存储元素,从这里也可以看出来,hashset内部是以hashmap实现的
private transient HashMap<E,Object> map;
//定义一个常量,在向map存储时的所有值都是用这个常量代替
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
二、构造函数
1.
//默认初始化一个HashMap对象
public HashSet() {
map = new HashMap<>();
}
2.
//可指定大小和负载比,但实际还是初始化一个hashmap对象
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
3.
//可指定容量大小,但初始化的还是hashmap对象
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
4.
//这次初始化的是一个linkedhashmap对象,可以看出最后一个参数暂时没用,但是有这个参数,就可以初始化为linkedhashmap对象
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
5.
//这个构造函数允许传入集合进行初始化
public HashSet(Collection<? extends E> c) {
//直接通过集合大小和默认负载比推算出应该初始化的容量,+1是为了防止出现小数向上取整
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
//添加元素
addAll(c);
}
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;//这一行我感觉没有太多意义,只要最后一个插入成功就是返回true,有知道的告诉我一下是不是有别的用
return modified;
}
三、添加方法--add
//可见内部还是调用的hashmap的put方法实现,我们知道HashMap的put方法如果该位置已经存在一个一样的Key,会用新的value替换原来的旧的value,并且返回旧的value,所以对于HashSet而言第一次插入返回null就代表成功,以后再次插入同样的元素,返回的是一个对象,表示已经存在这样的元素了,插入失败
public boolean add(E e) {
return map.put(e, PRESENT)==null;//这里可以看出为什么插入的默认值不能为null,因为为null的话,put之后返回的也为null,不能知道是插入了新的还是返回了老的null值
}
四、 删除方法--remove
//也是调用的hashmap的移除方法,同添加一样,通过返回的值判断是否删除成功
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}