混淆hashmap#resize

时间:2017-05-26 13:36:26

标签: java hashmap

在阅读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分支中拥有这么多代码?

2 个答案:

答案 0 :(得分:0)

修改 当表格变大时,树木化bin的阈值会发生变化。这就是它正在做的事情。

我还没有阅读整个文件,但这可能是一个可能的原因(第220行)

  

普通与树模式之间的使用和转换是   复杂的子类LinkedHashMap的存在。看到   下面定义了在插入时调用的钩子方法,   删除和访问允许LinkedHashMap内部   否则保持独立于这些机制。 (这也是   要求将映射实例传递给某些实用程序方法   这可能会创建新的节点。)

答案 1 :(得分:0)

调整大小时,每个垃圾箱都分为两个单独的垃圾箱。因此,如果容器中包含几个链接的项目,则不能根据第一项的哈希将它们全部移入单个目标容器中:您应重新检查所有哈希并将它们散布到“ hi”和“ lo”容器中,具体取决于散列((e.hash & oldCap) == 0)中的新有效位。在引入树框之前的Java 7中,这有些简单,但是较旧的算法可以更改项目的顺序,而现在这是不可接受的。