afterNodeAccess函数
void afterNodeAccess(Node<K,V> e) { // move node to last LinkedHashMap.Entry<K,V> last; // 如果定义了accessOrder,那么就保证最近访问节点放到最后 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; } } |
就是说在进行put之后就算是对节点的访问了,那么这个时候就会更新链表,把最近访问的放到最后,保证链表。
afterNodeInsertion函数
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);
}
}
如果用户定义了removeEldestEntry的规则,那么便可以执行相应的移除操作。
afterNodeRemoval函数
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;
}
这个函数是在移除节点后调用的,就是将节点从双向链表中删除。
我们从上面3个函数看出来,基本上都是为了保证双向链表中的节点次序或者双向链表容量所做的一些额外的事情,目的就是保持双向链表中节点的顺序要从eldest到youngest。
3. put和get函数
put函数在LinkedHashMap中未重新实现,只是实现了afterNodeAccess和afterNodeInsertion两个回调函数。get函数则重新实现并加入了afterNodeAccess来保证访问顺序,下面是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;
}
值得注意的是,在accessOrder模式下,只要执行get或者put等操作的时候,就会产生structural modification。官方文档是这么描述的:
A structural modification is any operation that adds or deletes one or more mappings or, in the case of access-ordered linked hash maps, affects iteration order. In insertion-ordered linked hash maps, merely changing the value associated with a key that is already contained in the map is not a structural modification. In access-ordered linked hash maps, merely querying the map with get is a structural modification.
不要犯了像ConcurrentModificationException with LinkedHashMap类似的问题。
总之,LinkedHashMap不愧是HashMap的儿子,和老子太像了,当然,青出于蓝而胜于蓝,LinkedHashMap的其他的操作也基本上都是为了维护好那个具有访问顺序的双向链表。:-)