實現HashMap的順序儲存
從Java API知道,LinkedHashMap繼承於HashMap,並且通過雙向連結串列儲存各節點的位置資訊,實現了順序儲存。但是如果讓你自己寫一個順序儲存的HashMap,將如何下手呢?從研究LinkedHashMap的原始碼開始入手,究竟它比HashMap多了哪些東西,讓它擁有了順序儲存的能力。
1.放入元素(put)
從放入一個元素開始,即最常見的V put(K key, V value)方法入手,LinkedHashMap並沒有重寫HashMap的put方法,但是它重寫了最關鍵的Node<K, V> newNode(int hash, K key, V value, Node next)方法,該方法首先建立一個HashMap.Node的子類LinkedHashMap.Entry,它比Node多了兩個指標Entry<K, V> before, after;//用於儲存前後兩個節點的資訊:
LinkedHashMap.Entry<K, V>內部類
其次,把要放入的元素插入雙向連結串列的表尾:
增加元素到雙向連結串列的末尾
注意:LinkedHashMap擁有兩個瞬時的屬性transient LinkedHashMap.Entry<K,V> tail;//用於儲存上一個元素,即表尾;transient LinkedHashMap.Entry<K, V> head;//用於儲存第一個元素,即表頭。
2.遍歷元素(entrySet)
LinkedHashMap重寫了Map介面的Set<Map.Entry<K, V> entrySet()方法,並返回自己的內部類class LinkedEntrySet extends AbstractSet<Map.Entry<K, V>>
下面可以看下LinkedHashIterator的nextNode方法的實現:
LinkedHashIterator的nextNode方法
正是nextNode方法使用了LinkedHashMap.Entry<K, V>的after屬性,使得iterator的遍歷按照放入順序進行的。
3.獲取元素(get)
LinkedHashMap重寫了Map介面的V get(Object key)方法,該方法分兩個步驟:1.呼叫父類HashMap的getNode(hash(key),key)方法,獲取value;2.如果accessOrder為true(預設為false),那麼移動所訪問的元素到表尾,並修改head和tail的值:
訪問後重排序(accessOrder)