一、LinkedHashMap數據結構
LinkedHashMap是建立在HashMap的數組、鏈表和紅黑樹的基礎上,添加了一個雙向循環列表,將HashMap中的元素鏈接起來。
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
繼承自HashMap中的next是用於維護HashMap指定table位置上連接的node的順序的。
before、after是用於維護Entry(繼承自HashMap中的Node)插入的先後順序的。
二、底層操作
2.1 linkNodeLast():
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;
last.after = p;
}
}
2.2 transferLinks():
應用src鏈接到dst,用dst替換src。
private void transferLinks(LinkedHashMap.Entry<K,V> src, LinkedHashMap.Entry<K,V> dst) {
LinkedHashMap.Entry<K,V> b = dst.before = src.before;
LinkedHashMap.Entry<K,V> a = dst.after = src.after;
if (b == null)
head = dst;
else
b.after = dst;
if (a == null)
tail = dst;
else
a.before = dst;
}
2.3 afterNodeRemoval():
取消鏈接節點,但是沒有刪除節點,不利於JVM進行垃圾回收 void afterNodeRemoval(Node<K,V> e) {
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;
}
2.4 afterNodeInsertion()
可能刪除長者
void afterNodeInsertion(boolean evict) {
LinkedHashMap.Entry<K,V> first;
if (evict && (first = head) != null && removeEldestEntry(first)) {
K key = first.key;
removeNode(hash(key), key, null, false, true);
}
}
2.5 afterNodeAccess()
將節點移動到最後 void afterNodeAccess(Node<K,V> e) {
LinkedHashMap.Entry<K,V> last;
//若訪問順序爲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;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
tail = p;
++modCount;
}
}
三、實現的主要方法
通過調用底層操作完成。
//如果此映射將一個或多個鍵映射到指定的值,則返回true。
public boolean containsValue(Object value) {
for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after) {
V v = e.value;
if (v == value || (value != null && value.equals(v)))
return true;
}
return false;
}
//返回指定鍵映射到的值,如果此映射不包含鍵的映射,則返回null。
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;
}
//返回指定鍵映射到的值,如果此映射不包含鍵的映射,則返回defaultValue。
public V getOrDefault(Object key, V defaultValue) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null) //調用父類HashMap中的getNode方法
return defaultValue;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}
//從此地圖中刪除所有的映射。
public void clear() {
super.clear();
head = tail = null;
}
//如果此地圖應刪除其最老的條目,則返回true。
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
}