【问题标题】:how does addbefore method work in LinkedHashMapAddbefore 方法在 LinkedHashMap 中如何工作
【发布时间】:2017-08-01 14:38:49
【问题描述】:

我在看LinkedHashMap的源码,addBefore方法让我很困惑:

private void addBefore(Entry<K,V> existingEntry) {
            after  = existingEntry;
            before = existingEntry.before;
            before.after = this;
            after.before = this;
}

这个方法在createEntry方法中被调用:

void createEntry(int hash, K key, V value, int bucketIndex) {
        HashMap.Entry<K,V> old = table[bucketIndex];
        Entry<K,V> e = new Entry<>(hash, key, value, old);
        table[bucketIndex] = e;
        e.addBefore(header);
        size++;
}

很明显,传递给addBefore方法的参数始终是header entry,所以addBefore方法中的after变量始终是header entry。此外,头节点永远不会改变。

我的问题是 addBefore 方法是如何形成双向链表的?

【问题讨论】:

  • 我不清楚this 是如何分配自己的afterbefore 指针的。我想如果你能解释一下,那么你的问题就会得到答案。
  • 画几张图就明白了。如果你想在Node 之前插入,你知道NodeNode 在它前面插入它们之间。 existingEntry 是您要在之前添加新的NodeNode。所以在existingEntry之前找到Node。这个NodeexistingEntry.before。现在将新的Node 链接到'Node' 的末尾,在addBefore Node and to the beginning of the addBefore Node 之前。
  • @SedrickJefferson 你的解释缺少一些东西;这可能是 OP 感到困惑的地方。
  • 我同意@TimBiegeleisen。我认为一个图表可以很好地解释这一点。

标签: java linkedhashmap


【解决方案1】:

如果您注意到,LinkedHashMap 中的每个条目都有两个指针,之前和之后

static class Entry<K,V> extends HashMap.Node<K,V> {
    Entry<K,V> before, after;
    Entry(int hash, K key, V value, Node<K,V> next) {
        super(hash, key, value, next);
    }
}

我会逐行说明:

HashMap.Entry<K,V> old = table[bucketIndex];
Entry<K,V> e = new Entry<>(hash, key, value, old);
table[bucketIndex] = e;

这 3 行只是在哈希图中找到 bucketindex 的第一个条目,并将新节点添加到此存储桶列表的开头。所以这里传递的旧参数基本上变成了插入节点的next指针。

第 4 行调用 addBefore 方法,其中标头作为引用传递。

after = existingEntry → 这里existingEntry是header,after基本是this.after,所以有效的让新节点的after指针指向header。

before = existingEntry.before; → 这再次使新节点的前指针指向 header 的前,这是列表中的最后一个元素(它是一个循环双向链表)。

before.after = this; → 这使得 list 中最后一个节点的 after 指针(因为新节点的 before 现在指向 list 中的最后一个节点)指向我们要插入的新节点。

after.before = this; → 现在更改了 header 的 before 指针。必须更改标头的 before 因为列表中的最后一个节点现在是我们要插入的新节点,并且该语句有效地做到了。

因此,linkedhashmap 维护了一个循环双向链表,用于维护插入顺序/访问顺序(由 accessOrder 参数控制)。希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多