在阅读java.util.HashMap#resize
的{{3}}之后,我对某些部分感到非常困惑 - 也就是当某些bin
有多个节点时。
else { // preserve order
Node<K,V> loHead = null, loTail = null;
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
为什么我觉得这部分不需要存在?只需使用下面的代码
newTab[e.hash & (newCap - 1)] = e;
没问题 - 我认为它们具有相同的效果。
那么为什么要在else分支中拥有这么多代码?
答案 0 :(得分:0)
修改强> 当表格变大时,树木化bin的阈值会发生变化。这就是它正在做的事情。
我还没有阅读整个文件,但这可能是一个可能的原因(第220行)
普通与树模式之间的使用和转换是 复杂的子类LinkedHashMap的存在。看到 下面定义了在插入时调用的钩子方法, 删除和访问允许LinkedHashMap内部 否则保持独立于这些机制。 (这也是 要求将映射实例传递给某些实用程序方法 这可能会创建新的节点。)
答案 1 :(得分:0)
调整大小时,每个垃圾箱都分为两个单独的垃圾箱。因此,如果容器中包含几个链接的项目,则不能根据第一项的哈希将它们全部移入单个目标容器中:您应重新检查所有哈希并将它们散布到“ hi”和“ lo”容器中,具体取决于散列((e.hash & oldCap) == 0
)中的新有效位。在引入树框之前的Java 7中,这有些简单,但是较旧的算法可以更改项目的顺序,而现在这是不可接受的。