LinkedHashMap继承了HashMap,实现了Map接口。
它在HashMap的基础上为将每个插入节点添加了before和after两个指针,记录节点插入顺序,构成一个双向链表。
1. 源码分析
1.1. 构造方法
一共有五种构造方法,其中前四种默认accessOrder为false,然后直接调用HashMap的对应构造方法;第五种构造方法可以指定accessOrder为true/false。
public LinkedHashMap() {
super();
accessOrder = false;
}
1.2. newNode()
LinkedHashMap重写了HashMap中的newNode()方法,创建出一个LinkedHashMap.Entry对象,在Node的基础上增加了before和after个指针,形成双向链表(全局插入顺序双向)。
(prev和next这两个指针形成bucket内的双向链表)
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;
}
1.3. afterNodeInsertion()
LinkedHashMap重写了HashMap中的afterNodeInsertion(boolean evict)方法。evict:vt.逐出,驱逐
这个方法在LinkedHashMap中不起作用,因为removeEldestEntry方法始终返回false,但自定义类继承LinkedHashMap并重写该方法可以在指定条件下删除链表头部的旧节点。
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);
}
}
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
1.4. afterNodeAccess()
LinkedHashMap重写了HashMap中的get(Object key)、getOrDefault()方法。
增加了一次对accessOrder的判断,如果accessOrder为true,则会调用afterNodeAccess方法,将访问点移动到链表的末尾。
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;
}
/**
* {@inheritDoc}
*/
public V getOrDefault(Object key, V defaultValue) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null)
return defaultValue;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}