两个问题:
hashMap在添加值的时候,如果hash&(capacity-1)的位置在某个entry链的中间,也就是如下代码所示:
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
//问题一的地方
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
//问题二的地方
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
问题一,TREEIFY_THRESHOLD的默认值是8,也就是说,如果binCount的值为7的时候,链表存储就会转为红黑树存储,我想确认的是,这句话是不是说明,entry单个链最多存储6个元素,第七个元素的时候链表就会自动转换成红黑树了
问题二,问题二可以看出,如果在entry链的中间找到匹配的hash和key,就会跳出,然后还会执行下面一段代码:
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
也就是值的更新,那么我有个疑问,为什么在putVal的方法最后有一个判断语句:
if (++size > threshold)
resize();
如果是在entry链中间匹配到,那么这次的putVal算不算给这条entry链增加了长度呢,因为从上边的代码也可以看到,如果是中间匹配,他是直接更新值的。我的问题是,这条判断语句是否需要增加一个判断,判断是否中间匹配的判断。
如果是存在的key 他直接return oldValue; size不会再加1了。
确实是这样,我粗心了。
哪个JDK版本
JDK1.8的版本,然后刚刚我写了个测试,因为同样的key的hash运算是一样的,然后put两个同样的key,size值还是1,说明并没有完成size+1这个操作,只是更新了value,跟我的想法一样,那么是不是跟这边就自相矛盾,++size>threshold这个判断语句,size的值每次都会自动+1。