问题:在阅读java8中WeakHashMap源码时,发现一个问题,put操作在发生hash冲突时,只有替换操作,但是没有新增链表节点的操作,链表节点是什么时候链上去的?
java8中的put源码如下:
public V put(K key, V value) {
Object k = maskNull(key);
int h = hash(k);
Entry<K,V>[] tab = getTable();
int i = indexFor(h, tab.length);
//这里只是在链表上找到key存在的节点做替换,但是对于key不存在的情况,
//并没有创建新的节点链到原来的链表后面。
for (Entry<K,V> e = tab[i]; e != null; e = e.next) {
if (h == e.hash && eq(k, e.get())) {
V oldValue = e.value;
if (value != oldValue)
e.value = value;
return oldValue;
}
//?????当hash 相同但是key不同不是应该创建新节点链到链表上吗?
}
modCount++;
Entry<K,V> e = tab[i];
tab[i] = new Entry<>(k, value, queue, h, e);
if (++size >= threshold)
resize(tab.length * 2);
return null;
}
首先纠正一点
put操作在发生hash冲突时,只有替换操作
这句表述不正确。hash冲突是由于不同的k命中同一块地址,而替换操作明显是由于相同的k,相同的hash命中本该就是他的地方,这应该是正常寻址而已,正常寻址自然是要判断是否有
更新/替换
操作所以if的条件是用hash和key一起来判断的,只处理更新/替换操作
真正的hash冲突必然是会新增节点的。
weakhashmap 并没有对hash冲突时做什么特殊处理,单纯的就是添加到表头而已。只是提前做了
更新/替换
操作,确保之后保存的数据一定是新数据(非更新/非替换)。Entry
就是一个单链表你代码里面的new Entry(...)调用的是
你贴代码中的for循环不过是检测当前put操作是否为
替换\重复添加
操作,如果不是重复添加或者更新,而是由于新增不一样的数据,则执行for之后的代码。我把你贴的put方法加了些注释