Talk about LinkedHashMap in Java

When using HashMap, because the order of its insertion is random, and we want to traverse in the order of insertion. Then we can use LinkedHashMap.

Take a look at the source code of LinkedHashMap today to see how the insertion of HashMao is ordered.

1. Structure

public class LinkedHashMap<K,V>
    extends HashMap<K,V>

    First of all, it inherits from HashMap, but to realize the insertion order, the insertion order of each node must be recorded, so LinkedHashMap rewrites MapEntry

static class Entry< K , V > extends HashMap.Node< K , V > {
     //before is the predecessor node of the node, after is the successor node of the node
     LinkedHashMap.Entry< K , V > before , after ;
 Entry ( int hash , K key , V value , HashMap.Node< K , V > next) {
         super (hash , key , value , next)    ;
    }
}
    Two attributes are added to the nodes of HashMap, one is the front node and the other is the back node, to record the insertion order of the nodes.

Second, the realization of the query order

    In order to ensure the record insertion order, each inserted node is connected with a linked list, so LinkedHashMap maintains a header and a footer.

transient LinkedHashMap.Entry<K,V> head;
/**
 * The tail (youngest) of the doubly linked list.
 */
transient LinkedHashMap.Entry<K,V> tail;

Third, insert the node

    Same as hashMap, but LinkedHashMap overrides the newNode method.

Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
    LinkedHashMap.Entry<K,V> p =
        new LinkedHashMap.Entry<K,V>(hash, key, value, e);
    linkNodeLast(p);
    return p;
}

    So what exactly does LinkedHashMap do when inserting a node, we can enter the linkNodeLast method

private void linkNodeLast(LinkedHashMap.Entry<K , V> p) {
     // Insert the current node at the end of the linked list
     LinkedHashMap.Entry<K , V> last = tail ;
     tail = p ;
 // If last is empty, it indicates the collection There is no node yet, so the node p is set as the head node
 if (last == null )        
        head = p ;
 // If last is not empty, put p behind the original last node . Modify the front node pointer of the node p , and modify the original last node's back pointer
 else {        
        p.before = last;
        last.after = p;
    }
}

可以看到,每次插入都将新节点加到链表的末尾,并用节点的before和after指针指向前置节点和后置节点。以此记录节点顺序。

LinkedHashMap节点的删除

void afterNodeRemoval(Node<K,V> e) { // unlink
    //找出要删除节点的前置节点b和后继节点p
    LinkedHashMap.Entry<K,V> p =
            (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
    //释放节点p的所有引用
    p.before = p.after = null;
    //如果要删除节点为头结点,则将头节点指针指向要删除节点p的后继,也就是p
    if (b == null)
        head = a;
    //如果要删除节点不为头结点,则将要删除节点p的前置节点的后继指针p.before指向要删除节点的后继节点
    else
        b.after = a;
    //如果要删除节点为尾结点,则将尾节点指针指向要删除节点p的前置,也就是b
    if (a == null)
        tail = b;
    //如果要删除节点不为尾结点,则将要删除节点p的后继节点的前置指针a.before指向要删除节点的前置节点
    else
        a.before = b;
}

因为LinkedHashMap重写了afterNodeRemoval方法,可以看出,在删除节点时,将节点从记录插入顺序的链表中删除,还是原先对应的插入顺序。

总结:

        LinkedHashMap使用两个指针记录节点的插入顺序

        LinkedHashMap继承了hashMap,所以只需将改变hashMap结构的某些方法进行重写即可。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325667839&siteId=291194637