Java addbefore方法在LinkedHashMap中是如何工作的

Java addbefore方法在LinkedHashMap中是如何工作的,java,linkedhashmap,Java,Linkedhashmap,我正在查看LinkedHashMap的源代码,addBefore方法让我很困惑: private void addBefore(Entry<K,V> existingEntry) { after = existingEntry; before = existingEntry.before; before.after = this; after.before = this; } priv

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

private void addBefore(Entry<K,V> existingEntry) {
            after  = existingEntry;
            before = existingEntry.before;
            before.after = this;
            after.before = this;
}
private void addBefore(条目existingEntry){
之后=现有条目;
before=existingEntry.before;
在此之前。之后=此;
之后。之前=这个;
}
在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++;
}
void createEntry(int散列、K键、V值、int bucketinex){
条目old=表[bucketIndex];
条目e=新条目(散列、键、值、旧条目);
表[Bucketinex]=e;
e、 addBefore(标题);
大小++;
}
很明显,传入addBefore方法的参数始终是头条目,因此addBefore方法中的after变量始终是头条目。此外,标头节点从未更改


我的问题是addBefore方法如何形成一个双链接列表?

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

静态类条目扩展了HashMap.Node{
入境前、入境后;
条目(int散列、K键、V值、节点下一个){
super(散列、键、值、下一个);
}
}
我会一行一行地说:

HashMap.Entry<K,V> old = table[bucketIndex];
Entry<K,V> e = new Entry<>(hash, key, value, old);
table[bucketIndex] = e;
HashMap.Entry old=表[bucketIndex];
条目e=新条目(散列、键、值、旧条目);
表[Bucketinex]=e;
这三行只是在hashmap中找到bucketindex的第一个条目,并将新节点添加到此bucket列表的开头。因此,这里传递的旧参数基本上成为插入节点的下一个指针

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

after=existingEntry
→ 这里现有的条目是header,after基本上是this.after,因此它有效地使新节点的after指针指向header

before=existingEntry.before→ 同样,这使得新节点的before指针指向列表中最后一个元素(循环双链接列表)的头的before

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

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


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

我不清楚
这个
如何在
之后和
之前分配
指针。我想如果你能解释一下,那么你就会得到你问题的答案。画一些图表,这是有意义的。如果要在
节点
之前插入,则必须知道
节点
及其前面的
节点
,以便在它们之间插入
existingEntry
是您要在之前添加新
节点的
节点。因此,在
现有条目之前找到
节点
。此
节点
现有条目。在
之前。现在,将新的
节点
链接到addBefore
节点之前的“节点”末尾和addBefore
节点的开头;这可能是OP感到困惑的地方。只要检查这些图表:我同意@TimBiegeleisen。我想用图表来解释这一点会很好。
HashMap.Entry<K,V> old = table[bucketIndex];
Entry<K,V> e = new Entry<>(hash, key, value, old);
table[bucketIndex] = e;