java8 LinkedHashMap源碼分析

繼承了HashMap 實現了 Map接口

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

雙向鏈表頭結點

transient LinkedHashMap.Entry<K,V> head;

雙向鏈表尾結點

 transient LinkedHashMap.Entry<K,V> tail;

默認false維護的是插入順序,true維護的是訪問順序。

 final boolean accessOrder;

默認是維護插入的順序

 public LinkedHashMap() {
        super();
        accessOrder = false;
    }

put元素的時候LinkeHashMap重寫了newNode方法,會把Entry插入到雙向鏈表的最後位置。這樣就維護了插入順序。

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

get方法 在hashMap的getNode方法基礎上,如果accessOrder=true,也就是訪問有序的話,就會將當前獲取的節點插入到雙向鏈表的尾部。也就是LRU的思想(最近經常使用的以後出現的概率也高,然後不經常使用的會優先淘汰)

 public V get(Object key) {
        Node<K,V> e;
        if ((e = getNode(hash(key), key)) == null)
            return null;
        if (accessOrder)
            afterNodeAccess(e);
        return e.value;
    }

移到節點到最後

 void afterNodeAccess(Node<K,V> e) { // move node to last
        LinkedHashMap.Entry<K,V> last;
        if (accessOrder && (last = tail) != e) {
            LinkedHashMap.Entry<K,V> p =
                (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
            p.after = null;
            if (b == null)
                head = a;
            else
                b.after = a;
            if (a != null)
                a.before = b;
            else
                last = b;
            if (last == null)
                head = p;
            else {
                p.before = last;
                last.after = p;
            }
            tail = p;
            ++modCount;
        }
    }

遍歷順序就是根據雙向鏈表從head依次從前往後遍歷。

 public void forEach(BiConsumer<? super K, ? super V> action) {
        if (action == null)
            throw new NullPointerException();
        int mc = modCount;
        for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
            action.accept(e.key, e.value);
        if (modCount != mc)
            throw new ConcurrentModificationException();
    }

總結

LinkedHashMap 就是維護了插入順序或者訪問順序的HashMap。
如果設置了維護訪問順序,某個元素被訪問,這個元素會移動到最後,遍歷時最後纔會到這個元素。

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