HashMap
的子類.accessOrder
爲true
,將更新元素放置到隊末.HashMap
進行過多重寫.主要經過實現afterNode*
相關方法,在數據結構變動後,進行後置的鏈表
結構更新進行維護.linkNodeLast
方法head
與tail
.head
與tail
初始化完成後,負責將目標元素p
鏈接到tail
並更新原有tail
到目標元素p
private void linkNodeLast(LinkedHashMap.Entry<K,V> p) { // 緩存尾部 LinkedHashMap.Entry<K,V> last = tail; // 更新尾部到新元素 tail = p; // 判斷老尾部是否已經初始化 if (last == null) // 老尾部爲初始化,表明頭部也沒初始化.進行初始化操做 head = p; else { // 初始化以完成,將p連接到老尾部以後 p.before = last; last.after = p; } }
transferLinks
方法使用dst
替換src
在雙向鏈表中的位置java
private void transferLinks(LinkedHashMap.Entry<K,V> src, LinkedHashMap.Entry<K,V> dst) { // 同步before,同時保存到局部變量 LinkedHashMap.Entry<K,V> b = dst.before = src.before; // 同步after,同時保存到局部變量 LinkedHashMap.Entry<K,V> a = dst.after = src.after; // 檢查before if (b == null) // 沒有before.將dst設置爲head節點 head = dst; else // 有before,將before與dst關聯 b.after = dst; // 檢查after if (a == null) // 沒有after,將dst做爲tail節點 tail = dst; else // 有after,將after與dst鏈接 a.before = dst; }
newNode
方法重寫了父類newNode
方法.擴展雙向鏈表的鏈接操做.返回了HashMap.Node
的子類節點LinkedHashMap.Entry
.node
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; }
replacementNode
方法擴展雙向鏈表替換節點的操做.這個方法用於父類HashMap
將HashMap.TreeNode
替換爲HashMap.Node
時調用,這裏進行了重寫,使用帶有雙向鏈表的LinkedHashMap.Entry
做爲返回值
注意: 這裏HashMap.TreeNode
是實現了LinkedHashMap.Entry
的.也就是參數p
,他能夠直接強轉爲實現類LinkedHashMap.Entry
算法
Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) { LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p; LinkedHashMap.Entry<K,V> t = new LinkedHashMap.Entry<K,V>(q.hash, q.key, q.value, next); // 替換節點 transferLinks(q, t); return t; }
newTreeNode
方法重寫了父類方法newTreeNode
.擴展雙向鏈表的鏈接操做.一樣,由於HashMap.TreeNode
實現LinkedHashMap.Entry
.能夠直接經過linkNodeLast
方法進行鏈接操做緩存
TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) { TreeNode<K,V> p = new TreeNode<K,V>(hash, key, value, next); linkNodeLast(p); return p; }
replacementTreeNode
方法同replacementNode
.擴展雙向鏈表替換節點的操做.只是節點類型變成了TreeNode
.又由於他是LinkedHashMap.Entry
的子類,能夠直接交給transferLinks
使用.進行雙向鏈表替換操做數據結構
TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) { LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p; TreeNode<K,V> t = new TreeNode<K,V>(q.hash, q.key, q.value, next); transferLinks(q, t); return t; }
afterNodeRemoval
方法刪除節點後調用.進行雙向鏈表同步code
void afterNodeRemoval(Node<K,V> e) { // unlink // b - before節點 // p - 被刪除節點 // a - after節點 LinkedHashMap.Entry<K,V> p = (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after; // 清除p的雙端引用 p.before = p.after = null; // 判斷before是否存在 if (b == null) // 沒有before // 設置a爲head head = a; else // 存在before // 鏈接b->a.注意,這是單向鏈接,如今還沒法確認a是否存在.若是a爲空,b就是鏈表中的惟一節點.after屬性爲null b.after = a; // 判斷a是否爲空 if (a == null) // a爲空 // tail設置爲b tail = b; else // a存在 // 鏈接 a->b.注意,這裏也是單向鏈接.若是b是空的話,a如今就是head且before屬性是null a.before = b; }
afterNodeAccess
方法更新節點後調用.進行雙向鏈表同步對象
void afterNodeAccess(Node<K,V> e) { // move node to last // oldTail.老尾部緩存 LinkedHashMap.Entry<K,V> last; // 判斷accessOrder.即按照訪問(更新)順序排列 // 獲取老尾部 // 判斷當前元素是否是尾部元素 if (accessOrder && (last = tail) != e) { // accessOrder==true且e不要尾部元素 // b - fefore // p - 當前元素 // a - after LinkedHashMap.Entry<K,V> p = (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after; // 由於p將變爲尾部元素,因此直接設置p.after爲null. p.after = null; // 判斷b if (b == null) // b爲null,p節點就是head節點 // a做爲頭部節點 head = a; else // b不爲空 // 鏈接b->a. 注意,這裏是單向鏈接.a可能爲null,a.before的鏈接交給後續判斷 b.after = a; // 判斷a if (a != null) // a不爲空 // a->b.注意,這裏是單向連接.b多是null.b.after的鏈接交給後續判斷 a.before = b; else // a爲空.p節點就是tail節點 // 這裏有兩個分支,須要判斷b是否爲空.此處a已經爲空,若是b也爲空,說明p是列表中的惟一節點.這個判斷委託到後續判斷中處理 // 此時,last變量已經失去意義,它與p爲同一對象. // 這裏說一下賦值last = b;的做用.注意,這是本人猜想! // 是爲了統一算法的外在樣式.由於變量last在在本方法中是不會爲空的,且在全部的情形中,都會調用p.before = last;last.after = p;進行鏈接(除了p是惟一元素的狀況). // 那麼在b存在的時候,再次與p進行鏈接,在鏈表結構上也是沒有問題的,統一被視做被操做元素的前一個元素 last = b; if (last == null) // p是惟一元素 head = p; else { // 鏈接到尾部節點 p.before = last; last.after = p; } // 更新尾部節點到p tail = p; // 修改計數++ ++modCount; } }
LinkedHashIterator
封裝了針對鏈表結構的迭代器.並向子類提供了共有的擴展方法.繼承
abstract class LinkedHashIterator { LinkedHashMap.Entry<K,V> next; LinkedHashMap.Entry<K,V> current; int expectedModCount; LinkedHashIterator() { // 初始化next節點爲當前head next = head; expectedModCount = modCount; current = null; } public final boolean hasNext() { return next != null; } final LinkedHashMap.Entry<K,V> nextNode() { // 緩存next LinkedHashMap.Entry<K,V> e = next; // fast-fail if (modCount != expectedModCount) throw new ConcurrentModificationException(); // next爲空 if (e == null) throw new NoSuchElementException(); // 設置當前 current = e; // 更新next到下一個 next = e.after; return e; } public final void remove() { // 獲取當前 Node<K,V> p = current; // null判斷 if (p == null) throw new IllegalStateException(); // fast-fail if (modCount != expectedModCount) throw new ConcurrentModificationException(); // 迭代器置空 current = null; // 獲取key K key = p.key; // 調用父類的removeNode方法進行節點刪除 removeNode(hash(key), key, null, false, false); // 同步更新計數 expectedModCount = modCount; } }
LinkedHashIterator實現
分別繼承了LinkedHashIterator
並使用前者的nextNode
方法返回不一樣數據rem
final class LinkedKeyIterator extends LinkedHashIterator implements Iterator<K> { public final K next() { return nextNode().getKey(); } } final class LinkedValueIterator extends LinkedHashIterator implements Iterator<V> { public final V next() { return nextNode().value; } } final class LinkedEntryIterator extends LinkedHashIterator implements Iterator<Map.Entry<K,V>> { public final Map.Entry<K,V> next() { return nextNode(); } }