實現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()條件判斷成立,刪除第一個頭結點

小夥伴們都學會了嗎

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