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节点。

posted @ 2023-04-23 06:29  Jimmyhus  阅读(28)  评论(0编辑  收藏  举报