LinkedHashMap

LinkedHashMap 繼承自 HashMap,與 HashMap 相比,增加了一個功能:每個節點使用雙向鏈表鏈接起來,這樣就能保證節點的遍歷順序與插入順序一致。

這是 HashMap 的節點:

    static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;
        ...
    }

這是 LinkedHashMap 節點:

    static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
        TreeNode<K,V> parent;  // red-black tree links
        TreeNode<K,V> left;
        TreeNode<K,V> right;
        TreeNode<K,V> prev;    // needed to unlink next upon deletion
        boolean red;
        ...
    }

這裏的 TreeNode 並不是寫在 LinkedHashMap.java 裏面,而是寫在 HashMap 裏面的。因爲 LinkedHashMap 繼承自 HashMap,繼承了 HashMap 的很多方法:

clone, compute, computeIfAbsent, computeIfPresent, containsKey, isEmpty, merge, put, putAll, putIfAbsent, remove, remove, replace, replace, size

所以 LinkedHashMap 並沒有寫自己的 put 方法,而是直接重用了 HashMap 的 put 方法。看一下 HashMap 的 put 方法:

    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null); // check here
        ...
    }

    /* ------------------------------------------------------------ */
    // LinkedHashMap support


    /*
     * The following package-protected methods are designed to be
     * overridden by LinkedHashMap, but not by any other subclass.
     * Nearly all other internal methods are also package-protected
     * but are declared final, so can be used by LinkedHashMap, view
     * classes, and HashSet.
     */

    // Create a regular (non-tree) node
    Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) {
        return new Node<>(hash, key, value, next);
    }

在 HashMap 裏面,newNode 返回的是一個 Node,但是 LinkedHashMap 裏面,重寫了這個方法:

    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;
    }
    private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
        LinkedHashMap.Entry<K,V> last = tail;
        tail = p;
        if (last == null)
            head = p;
        else {
            p.before = last;
            last.after = p;
        }
    }

    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);
        }
    }

果然,這裏創建一個 LinkedHashMap.Entry,並且將他插入到隊列尾部。LinkedHashMap.Entry 是 HaspMap.Node 的子類。

 

參考鏈接:

1. https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章