Java 自定義實現 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本身做同步。
相關文章
- JS 實現快取演算法(FIFO/LRU)JS快取演算法
- CefSharp自定義快取實現快取
- LRU 快取淘汰演算法的兩種實現快取演算法
- 快取 LRU 和 LFU 實現快取
- LRU cache快取簡單實現快取
- 手把手使用 PHP 實現 LRU 快取淘汰演算法PHP快取演算法
- 常見快取演算法和LRU的c++實現快取演算法C++
- MUI呼叫原生自定義方法實現計算快取與清空快取UI快取
- 昨天面試被問到的 快取淘汰演算法FIFO、LRU、LFU及Java實現面試快取演算法Java
- 資料結構與演算法 | 如何實現LRU快取淘汰演算法資料結構演算法快取
- 看動畫理解「連結串列」實現LRU快取淘汰演算法動畫快取演算法
- LRU快取替換策略及C#實現快取C#
- Leetcode LRU快取,陣列+結構體實現LeetCode快取陣列結構體
- 演算法題:設計和實現一個 LRU Cache 快取機制演算法快取
- FIFO/LRU/LFU三種快取演算法快取演算法
- NodeJS中的LRU快取(CLOCK-2-hand)實現NodeJS快取
- LRU快取-實現雜湊連結串列結合快取
- Mybatis原始碼分析(七)自定義快取、分頁的實現MyBatis原始碼快取
- 146. LRU 快取快取
- LRU快取機制快取
- WebView自定義快取路徑WebView快取
- Android自定義View:快遞時間軸實現AndroidView
- 【golang必備演算法】 Letecode 146. LRU 快取機制Golang演算法快取
- 面試掛在了 LRU 快取演算法設計上面試快取演算法
- SpringBoot快取管理(三) 自定義Redis快取序列化機制Spring Boot快取Redis
- 利用LRU策略實現Axios請求快取iOS快取
- LSM-Tree - LevelDb之LRU快取快取
- LeetCode-146- LRU 快取機制LeetCode快取
- [Leetcode]146.LRU快取機制LeetCode快取
- 快取演算法:LRU、LFU、隨機替換等常見演算法簡介快取演算法隨機
- 常見面試題之作業系統中的LRU快取機制實現面試題作業系統快取
- Go 語言手寫本地 LRU 快取Go快取
- 什麼是LRU快取淘汰機制快取
- LeetCode146 動手實現LRU演算法LeetCode演算法
- LRU演算法四種實現方式介紹演算法
- EventSource的自定義實現
- Net 實現自定義Aop
- 自定義實現Complex類
- 自定義SpringMVC部分實現SpringMVC