AfterNodeInsertion方法
在Hashmap中它与其他后处理方法都是空实现:
// Callbacks to allow LinkedHashMap post-actions
void afterNodeAccess(Node<K,V> p) { }
void afterNodeInsertion(boolean evict) { }
void afterNodeRemoval(Node<K,V> p) { }
在LinkedHashMap中实现如下(LinkedHashMap继承了Hashmap):
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;
}
在LinkedHashMap中这个方法removeEldestEntry永远返回false,如果为true走的是移除head节点的逻辑。head节点就是最开始插入map的节点,也可以称为最旧的节点。
所以可以知道if判断永远是false,所以什么逻辑也不走。
但是我们先记住if判断里的条件,下面有用
上面的remove返回false,可以看出这些后处理方法不是给LinkedHashMap类和HashMap类使用的。用于继承了LinkedHashMap类的类使用,例如LRUCache,这个类所有代码如下
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 1L;
protected int maxElements;
public LRUCache(int maxSize) {
super(maxSize, 0.75F, true);
this.maxElements = maxSize;
}
@Override
protected boolean removeEldestEntry(Entry<K, V> eldest) {
return (size() > this.maxElements);
}
}
在LRUCache中重写了这个方法,作用是当当前链表大小大于最大容量时,移除一个最旧的元素,因为removeEldestEntry方法返回true,而且HashMap的put方法最后会调用afterNodeInsertion(true);这个方法的if判断只会判断三个条件,
第一个是传入的evict参数true还是false,evict英文是驱逐的意思,
第二个是当前head节点不为空
第三个则就是removeEldestEntry方法返回的参数
因此当LRUCache put元素时,会在put元素后调用后处理方法AfterNodeInsertion,它内部if条件判断里再调用removeEldestEntry方法,如果removeEldestEntry方法返回true,且头结点不为空,put方法默认调用后处理方法evict参数就是true,if条件判断3个条件都成立,所以LRUCache 此时会移除head节点。