LinkedHashMap 如何保證插入順序的(jdk8)


HashMap 大家知道,索引是(length-1) & hash 算出來的,是無序的,那么LinkedHashList是如何保證順序的呢?

答案就是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里有一些未實現的方法

    void afterNodeAccess(Node<K,V> p) { }
    void afterNodeInsertion(boolean evict) { }
    void afterNodeRemoval(Node<K,V> p) { }

看名稱其實就是在訪問,插入和刪除后的操作,這個其實就是為了LInkedHashMap維護鏈表而調用的,如果沒有這些方法,LInkedHashMap就要重寫putVal方法,這很沒必要。挑一個方法來看。

    void afterNodeRemoval(Node<K,V> e) { // unlink
        LinkedHashMap.Entry<K,V> p =
            (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
         將該位置的節點前驅和后繼節點置為空
        p.before = p.after = null;
        // 前驅節點為空,那么該節點的后繼節點就為head
        if (b == null)
            head = a;
        // 不為空,前驅節點的后繼節點為該節點的后繼節點
        else
            b.after = a;
        // 后繼節點為空,尾巴就是前驅節點
        if (a == null)
            tail = b;
        //不為空,則后繼節點的前驅節點,為該節點的前驅節點
        else
            a.before = b;
    }

接下來就是foreach遍歷了,可以看下和LInkedHashMap是重寫了這個方法的,和HashMap的不同

    //HashMap:
    public void forEach(BiConsumer<? super K, ? super V> action) {
        Node<K,V>[] tab;
        if (action == null)
            throw new NullPointerException();
        if (size > 0 && (tab = table) != null) {
            int mc = modCount;
            //  是用tab循環
            for (int i = 0; i < tab.length; ++i) {
                for (Node<K,V> e = tab[i]; e != null; e = e.next)
                    action.accept(e.key, e.value);
            }
            if (modCount != mc)
                throw new ConcurrentModificationException();
        }
    }


    //LInkedHashMap
    public void forEach(BiConsumer<? super K, ? super V> action) {
        if (action == null)
            throw new NullPointerException();
        int mc = modCount;
        //遍歷的是這個雙向鏈表,從head開始,所以是有序的,就是插入順序
        for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
            action.accept(e.key, e.value);
        if (modCount != mc)
            throw new ConcurrentModificationException();
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM