自己實現一個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()
條件判斷成立,刪除第一個頭結點
小夥伴們都學會了嗎