afterNodeAccess()/afterNodeInsertion()/afterNodeRemoval()
仔细一点会发现,HashMap中定义了三个空方法,还有注释表明了是专门给LinkedHashMap使用的回调方法,在LinkedHashMap中进行重写。
// Callbacks to allow LinkedHashMap post-actions
void afterNodeAccess(Node p) { }
void afterNodeInsertion(boolean evict) { }
void afterNodeRemoval(Node p) { }
先来看看afterNodeInsertion()这个方法,在HashMap中很多地方都有调用,在put()方法中也调用过,其中removeNode()方法还是HashMap里面的,对插入顺序关系进行修改,要注意的是removeEldestEntry()是直接返回了false,可以对这个方法进行重写,网上有一些文章使用LinkedHashMap实现简单的缓存就是需要自己重写这个方法,定义相关的废弃规则。
void afterNodeInsertion(boolean evict) { // possibly remove eldest
LinkedHashMap.Entry first;
if (evict && (first = head) != null && removeEldestEntry(first)) {
K key = first.key;
removeNode(hash(key), key, null, false, true);
}
}
而afterNodeAccess()方法则是在get()方法之后调用的,可以看到判断了accessOrder参数,也就是说在这里如果初始化的时候设置了accessOrder参数为true,这个方法就会实现上面那种get完一个元素后将它的顺序移到最后的效果。
void afterNodeAccess(Node e) { // move node to last
LinkedHashMap.Entry last;
if (accessOrder && (last = tail) != e) {
LinkedHashMap.Entry p =
(LinkedHashMap.Entry)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;
}
}
afterNodeRemoval()这个方法也是在HashMap中remove()方法调用的removeNode()方法中调用,也是对插入顺序之间关系的修改。
void afterNodeRemoval(Node e) { // unlink
LinkedHashMap.Entry p =
(LinkedHashMap.Entry)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;
}