实现LRU偷懒做法

自己实现一个LRU

做法:利用LinkedHashMap实现

import java.util.LinkedHashMap;
import java.util.Map;

public class CacheLRU {
    private Map<Integer,Integer> map;
    private final int CAPACITY;

    public CacheLRU(int CAPACITY){
        this.CAPACITY = CAPACITY;
        map = new LinkedHashMap<>(CAPACITY,0.75f,true){
            @Override
            protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
                return size() > CAPACITY; //容量大于capacity时就删除
            }
        };
    }

    public int get(int key){
        return map.getOrDefault(key,-1);
    }

    public void set(int key,int value){
        map.put(key,value);
    }

}

why?

为什么要用LinkedHashMap实现LRU,为什么它可以实现LRU?

我们重写了LinkedHashMap的removeEldestEntry方法,为什么要重写?

LinkedHashMap是HashMap的子类,扩展了一些功能

afterNodeInsertion()

这个方法在HashMap中是个空实现,但是在每一个put逻辑中都会调用这个方法,这不是明摆着要让别人去重写吗

//此处是在HashMap中
void afterNodeInsertion(boolean evict) { }

@Override
public V merge(K key, V value,BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
    /**省略一大段逻辑*/
    afterNodeInsertion(true);
		}
        return value;
}

@Override
public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
	/**省略*/		
    afterNodeInsertion(true);
        }
        return v;
}

@Override
public V computeIfAbsent(K key,Function<? super K, ? extends V> mappingFunction) {
    /**省略*/
    afterNodeInsertion(true);
    return v;
}

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {
    /**省略*/
    afterNodeInsertion(evict);
        return null;
}

而在LinkedHashMap中

ohhhhhhhhhhhhhhhh!!!他重写了!

我们来看看这段逻辑

void afterNodeInsertion(boolean evict) { // possibly remove eldest
        LinkedHashMap.Entry<K,V> first;
    	//如果evict为true,并且first不为空(其实就是这个map不为空),并且removeEldestEntry()方法返回的值为true
        if (evict && (first = head) != null && removeEldestEntry(first)) {
            K key = first.key;
            //删掉第一个节点(就是最开始插入的那个节点,因为LinkedHashMap是插入有序的)
            removeNode(hash(key), key, null, false, true);
        }
    }

这段逻辑最重要的一条,就是removeEldestEntry()这个方法,我们去看看LinkedHashMap自己是是怎么实现的

protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
        return false;
    }

嗯.默认返回false

什么意思?

意思就是啊,LinkedHashMap永远不会在插入元素之后删除第一个节点

除非你去重写removeEldestEntry()方法

我们重写了LinkedHashMap的removeEldestEntry()方法后

@Override
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
    return size() > CAPACITY; //容量大于capacity时就删除
}

size() > CAPACITY时返回true

于是LinkedHashMap中的afterNodeInsertion()条件判断成立,删除第一个头结点

小伙伴们都学会了吗

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章