標籤:java 開發
威哥說:
緩衝與APP應用的關係,好比西門慶與色,根本就離不開,而且地位最重,所以,小白們想成為老鳥,對待緩衝之情必需要深入,以下文章給你介紹了Java如果實現LRU(Least Recently Used)演算法,即最近最少使用演算法,這個演算法在Android開發中被用於圖片,內容的緩衝,我在《Android核心技術(下)》課程中就詳細講解了LRU的全部實現,有興趣的朋友可以登入扣丁學堂學習。
背景
LinkedHashMap繼承自HashMap,內部提供了一個removeEldestEntry方法,該方法正是實現LRU策略的關鍵所在,且HashMap內部專門為LinkedHashMap提供了3個專用回調方法,afterNodeAccess、afterNodeInsertion、afterNodeRemoval,這3個方法的字面意思非常容易理解,就是節點訪問後、節點插入後、節點刪除後分別執行的行為。基於以上行為LinkedHashMap就可以實現一個LRUCache的功能了。
關於LinkedHashMap的eldest:eldest字面意思為最老的,LinkedHashMap中有個叫做accessOrder的欄位,當accessOrder為true時表示LinkedHashMap內部節點按照訪問次數排序,最老的節點也就是訪問最少的節點。當accessOrder為false時表示LinkedHashMap內部節點按照插入順序排序,最老的節點也就是最早插入的節點,該值預設為false。
實現
自己實現LRUCache只需覆蓋removeEldestEntry這個方法即可,代碼如下
private static class LRUCache<K, V> extends LinkedHashMap<K, V>
{
private static final long serialVersionUID = -9111855653176630846L;
private static int MAX_ELEMENTS;
public LRUCache(int initCap, int maxSize) throws IllegalArgumentException
{
super(initCap, 0.75f, true);
if (maxSize < 0)
throw new IllegalArgumentException();
MAX_ELEMENTS = maxSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest)
{
return size() > MAX_ELEMENTS;
}
}
以上代碼需要一個MAX_ELEMENTS變數限制最大儲存節點個數,插入節點時判斷 如果當前節點個數已經超過了這個值則會根據LRU策略將訪問最少的那個節點刪除,這裡需要注意,預設LinkedHashMap保證的是插入順序,也就是節點按照插入先後來排序的,所以就算刪除也是刪除最先插入的節點,但是我們在建構函式中傳入了一個true,這個參數決定了LinkedHashMap內部的節點按照什麼方式排序,參數為true時說明內部節點按照最近訪問的時間排序,為false時說明按照插入順序排序。至此已完成了一個簡易的LRUCache實現。
注意
由於LinkedHahsMap本身實現不是安全執行緒的,也就是說這個LRUCache也不是安全執行緒的,如果想要能多線程訪問的話,可以這樣使用它:LRUCache cache = Collections.synchronizedMap(new LRUCache(10, 10))。這樣cache就可以在多線程下執行get\put等操作了,但是,用這種方式得到的cache在多線程遍曆時還是不安全的。所以不能在多線程下遍曆cache,官方文檔也建議在遍曆synchronizedmap時使用map本身做同步。
Java簡易LRU緩衝實現(開發技巧)