Hash table and linked list implementation of the Map interface,with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries.
LinkedHashMap實現了Map接口,繼承於HashMap,與HashMap不同的是它維持有一個雙鏈表,從而可以保證迭代時候的順序。
public class TestLinkedHashMap {
public static void main(String[] args) {
Map<String,String> map = new LinkedHashMap<String,String>();
map.put("數學","數學老師");
map.put("化學","化學老師");
map.put("物理","物理老師");
map.put("生物","生物老師");
map.put("政治","政治老師");
for(Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + "-->" + entry.getValue());
}
}
}
可以看出LinkedhashMap在HashMap 基礎上,用一個雙向的鏈表維持的插入時候的順序(默認,即accessOrder = false)。
public class TestLinkedHashMap {
public static void main(String[] args) {
//構造的時候 初始化容量爲16,負載因子爲0.75
//第三個參數爲accessOrder ,即迭代的順序。有按插入的順序和訪問時的順序。
//默認爲false,即按插入時候的順序進行迭代。設置爲true後,按訪問時候的順序進行迭代輸出,即鏈表的最後一個元素總是最近才訪問的。
Map<String,String> map = new LinkedHashMap<String,String>(16,0.75f,true);
map.put("數學","數學老師");
map.put("化學","化學老師");
map.put("物理","物理老師");
map.put("生物","生物老師");
map.put("政治","政治老師");
map.put("數學","數學老師");
for(Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + "-->" + entry.getValue());
}
}
}
此時調整鏈表如下:
LinkedHashMap部分源碼:
//鏈表第一個元素
transient LinkedHashMap.Entry<K,V> head;
//鏈表最後一個元素,當accessOrder = true的時候,表示最近使用的一個元素
transient LinkedHashMap.Entry<K,V> tail;
//迭代方式,默認爲false,即按插入時候的方式進行迭代
//若爲true,即按訪問時的順序進行迭代
final boolean accessOrder;
//五種構造方法
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
//默認爲false
accessOrder = false;
}
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}
public LinkedHashMap() {
super();
accessOrder = false;
}
public LinkedHashMap(Map<? extends K, ? extends V> m) {
super();
accessOrder = false;
putMapEntries(m, false);
}
//自定義accessOrder
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
......
//移除相應節點
void afterNodeRemoval(Node<K,V> e) { // unlink
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
p.before = p.after = null;
if (b == null)
head = a;
else
b.after = a;
if (a == null)
tail = b;
else
a.before = b;
}
//插入相應節點
void afterNodeInsertion(boolean evict) { // possibly remove eldest
LinkedHashMap.Entry<K,V> first;
if (evict && (first = head) != null && removeEldestEntry(first)) {
K key = first.key;
removeNode(hash(key), key, null, false, true);
}
}
//accessOrder = true的時候,保證最後一個節點是最近使用的
void afterNodeAccess(Node<K,V> e) { // move node to last
LinkedHashMap.Entry<K,V> last;
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;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
tail = p;
++modCount;
}
}
//get
public V get(Object key) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null)
return null;
if (accessOrder)
//按訪問的順序進行迭代,保證鏈表最後一個元素是最近使用的
afterNodeAccess(e);
//否則直接返回相應的值
return e.value;
}
總結:
LinkedHashMap是基於HashMap實現的,對於HashMap有認識,理解LinkedHashMap應該不難.LinkedHashMap使用一個雙向鏈表對鍵值度進行維護,創建LinkedHashMap的時候,默認accessOrder=false,迭代的時候爲插入時候的順序,只有第五種構造方法:
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {....}
可以使其迭代的方式變爲按訪問時候的順序。