需先看HashMap源碼:https://blog.csdn.net/yzh_1346983557/article/details/105456563
一、LinkedHashMap的成員變量
//雙向鏈表的頭結點
transient LinkedHashMap.Entry<K,V> head;
//雙向鏈表的尾結點
transient LinkedHashMap.Entry<K,V> tail;
//排序方式,true-訪問順序 false-插入順序
//默認是插入順序存儲:accessOrder = false;
//accessOrder = true時表示訪問順序存儲,就是最新訪問的數據會放到鏈表尾部!(訪問順序的LinkedHashMap進行了get操作以後,重新排序,把get的Entry移動到雙向鏈表的表尾。)
final boolean accessOrder;
LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>,可發現LinkedHashMap相比較HashMap多維護了2個成員變量head、tail,這2個變量就是LinkedHashMap實現雙向鏈表的關鍵變量。
二、LinkedHashMap的靜態內部類Entry
static class Entry<K,V> extends HashMap.Node<K,V> {
//新加成員變量before、after,用於雙向鏈表的連接
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
也是比HashMap.Node多維護了2個成員變量before、after,用於雙向鏈表的連接。
三、LinkedHashMap的newNode()方法
//HashMap.put()方法創建新Node會調用newNode()方法,LinkedHashMap重寫了HashMap的newNode()
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;
}
//將新節點加入雙向鏈表尾部
// link at the end of list
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;//舊尾節點作爲新節點的before
last.after = p;//新節點作爲舊尾節點的after
}
}
HashMap.put()方法創建新Node會調用newNode()方法,LinkedHashMap重寫了HashMap的newNode()。所以,往LinkedHashMap中put()數據時會調用linkNodeLast(),將新節點加入雙向鏈表。
jdk1.7是在構造函數中調用init()方法,init()中直接new Entry()創建了一個空節點對象作爲雙向鏈表的初始節點。jdk1.8去除了這一操作,沒有去new一個空節點作爲鏈表初始節點,這樣,鏈表中維護的節點就都是LinkedHashMap中實際存在的對象了。
四、LinkedHashMap.forEach()數據迭代方法
public void forEach(BiConsumer<? super K, ? super V> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
//從雙向鏈表的head開始,依次after迭代。所以取數據和存數據順序能相同。
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的數據結構圖
圖來源(侵權刪):https://www.jianshu.com/p/8f4f58b4b8ab
實際上圖是jdk1.7的LinkedHashMap的數據結構,jdk1.8中Entry header就是Entry1,偷懶拿來用一下。