1、特點
LinkedHashMap有序的,內部維護了一個雙向鏈表
2、LinkedHashMap是如何保證順序的
2.1 核心屬性
//是否根據操作順序排序
final boolean accessOrder;
//鏈表頭節點
transient LinkedHashMap.Entry<K,V> head;
//鏈表尾節點
transient LinkedHashMap.Entry<K,V> tail;
//當accessOrder=true是,LinkedHashMap鏈表順序不是根據插入的順序排序,而是根據操作的順序顯示
@Test
public void test4(){
LinkedHashMap<String,String> map = new LinkedHashMap(16,0.75f,true);
map.put("1","1");
map.put("2","2");
map.put("3","3");
map.get("1");
map.put("4","4");
map.put("3","33");
for(String key : map.keySet()){
System.out.println(key);
}
}
顯示結果爲:2 1 4 3
2.2、put()方法
/**
* 1、LinkedHashMap繼承了HashMap
* 2、put()方法走HashMap的put方法
*
* 改變:
* 在putVal()方法中,linkedHashMap重寫了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;
}
private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
LinkedHashMap.Entry<K,V> last = tail;
tail = p;
//如果尾節點爲空
if (last == null)
//則p爲頭節點
head = p;
else {
//如果尾結點不爲空,p的頭結點爲原始的尾結點,原始的尾結點的下一節點爲p
//這樣就形成了鏈表結構,就有了順序
p.before = last;
last.after = p;
}
}
3、LinkedHashMap獨特的功能
linkedHashMap可以根據操作順序排序
void afterNodeAccess(Node<K,V> e) {
LinkedHashMap.Entry<K,V> last;
//如果accessOrder=true,且當前節點不是尾結點
if (accessOrder && (last = tail) != e) {
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
p.after = null;
//如果當前節點的頭結點爲空,說明當前節點爲頭結點,將頭結點更新爲當前節點的尾結點
if (b == null)
head = a;
else
//如果當前節點不是頭結點,則將當前節點頭結點的尾結點更新爲當前節點的尾結點
b.after = a;
//如果當前節點的尾結點不爲空,則說明當前節點再中間不是尾結點,將尾結點的頭結點更新爲當前節點的頭結點
if (a != null)
a.before = b;
else
//如果當前節點是尾結點,則更新last爲b節點
last = b;
//如果last(可以理解爲倒數第二個節點)節點爲空,說明鏈表中只有一個元素,設置頭結點爲p
if (last == null)
head = p;
else {
//更新當前節點的前節點爲last,last的尾結點爲p
p.before = last;
last.after = p;
}
//設置尾結點爲p
tail = p;
//更新操作次數
++modCount;
}
}