LinkedHashMapの詳細

6387 ワード

LinkedHashMapには重要なデータがあります.
    // LinkedEntry        。            ,           before        after    
    static class LinkedEntry<K, V> extends HashMapEntry<K, V> {
        LinkedEntry nxt;
        LinkedEntry prv;

        /** Create the header entry */
        LinkedEntry() {
            super(null, null, 0, null);
            nxt = prv = this;
        }

        /** Create a normal entry */
        LinkedEntry(K key, V value, int hash, HashMapEntry next,
                    LinkedEntry nxt, LinkedEntry prv) {
            super(key, value, hash, next);
            this.nxt = nxt;
            this.prv = prv;
        }
    }

次に、ソースコードを見てみましょう.
public class LinkedHashMap<K, V> extends HashMap<K, V> {
    //    transient        ,      ,        。       , transient                  。
    transient LinkedEntry header;

    /**
     * True if access ordered, false if insertion ordered.
     */
    private final boolean accessOrder;

    //   header prv  ,    tail
    @Override 
    void addNewEntry(K key, V value, int hash, int index) {
        LinkedEntry header = this.header;

        // Remove eldest entry if instructed to do so.
        LinkedEntry eldest = header.nxt;
        if (eldest != header && removeEldestEntry(eldest)) {
            remove(eldest.key);
        }

        // Create new entry, link it on to list, and put it into table
        LinkedEntry oldTail = header.prv;
        LinkedEntry newTail = new LinkedEntry(
                key, value, hash, table[index], header, oldTail);
        table[index] = oldTail.nxt = header.prv = newTail;
    }


    //     HashMap   ,         accessOrder   
    @Override 
    public V get(Object key) {
        /*
         * This method is overridden to eliminate the need for a polymorphic
         * invocation in superclass at the expense of code duplication.
         */
        if (key == null) {
            HashMapEntry e = entryForNullKey;
            if (e == null)
                return null;
            if (accessOrder)
                makeTail((LinkedEntry) e);
            return e.value;
        }

        // Replace with Collections.secondaryHash when the VM is fast enough (http://b/8290590).
        int hash = secondaryHash(key);
        HashMapEntry[] tab = table;
        for (HashMapEntry e = tab[hash & (tab.length - 1)];
                e != null; e = e.next) {
            K eKey = e.key;
            if (eKey == key || (e.hash == hash && key.equals(eKey))) {
                //        ,     e     
                if (accessOrder)
                    makeTail((LinkedEntry) e);
                return e.value;
            }
        }
        return null;
    }

    //  e     header      
    private void makeTail(LinkedEntry e) {
        //  e     
        e.prv.nxt = e.nxt;
        e.nxt.prv = e.prv;

        //  e     header       
        LinkedEntry header = this.header;
        LinkedEntry oldTail = header.prv;
        e.nxt = header;
        e.prv = oldTail;
        oldTail.nxt = header.prv = e;
        modCount++;
    }
}

LinkedHashMapはputメソッドを実装せず、HashMapのputメソッドのaddNewEntryを複写しています
ここでまとめることができる.データを追加します.配列内の対応するindexを見つけてから、チェーンテーブルの最後の位置にデータを配置します.双方向チェーンテーブルなのでheaderに置くのと同じです.prv 2.データを取得します.配列内の対応するindexを見つけてから、データが存在する場所を見つけます.読み取り順に並べ替えられている場合は、このノードを双方向チェーンテーブルの最後のビットに配置します(この特性では、LRUアルゴリズムを実装できます).
参照先:http://wiki.jikexueyuan.com/project/java-collection/linkedhashmap.html http://blog.csdn.net/ns_code/article/details/37867985