自己实现一个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()
条件判断成立,删除第一个头结点
小伙伴们都学会了吗