前情提要
在Leetcode上遇到這樣一道題:
146. LRU緩存機制
運用你所掌握的數據結構,設計和實現一個 LRU (最近最少使用) 緩存機制。
它應該支持以下操作: 獲取數據 get 和 寫入數據 put 。
獲取數據 get(key) - 如果密鑰 (key) 存在於緩存中,則獲取密鑰的值(總是正數),否則返回 -1。
寫入數據 put(key, value) - 如果密鑰不存在,則寫入其數據值。
當緩存容量達到上限時,它應該在寫入新數據之前刪除最近最少使用的數據值,從而爲新的數據值留出空間。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/lru-cache
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
當時第一想法是用HashMap存儲(key,value),用LinkedList作爲隊列存儲最近的使用情況。
但是看了參考答案之後,發現java中有種數據結構能夠直接滿足題目需求,那就是LinkedHashMap,官方給的代碼乍一看也不太明白。
代碼如下:
class LRUCache extends LinkedHashMap<Integer, Integer>{
private int capacity;
public LRUCache(int capacity) {
super(capacity, 0.75F, true);
this.capacity = capacity;
}
public int get(int key) {
return super.getOrDefault(key, -1);
}
public void put(int key, int value) {
super.put(key, value);
}
@Override
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
return size() > capacity;
}
}
/**
* LRUCache 對象會以如下語句構造和調用:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
LinkedHashMap
數據結構
LinkedHashMap繼承於HashMap,結點類型如下:
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
對於它的結構,我們可以用一個圖表示:
簡單的說,LinkedHashMap其實就是在HashMap的基礎上加入了雙向鏈表,來保持順序性,這個順序默認是插入順序,可以通過設置accessOrder設置爲訪問順序。
具體可以參考這篇文章圖解LinkedHashMap原理,寫得很好很詳細。
常用方法
(1)構造方法
方法 | 作用 |
LinkedHashMap() | 用默認初始容量(16)和負載因子(0.75)構造空插入有序的LIKEDHHMAP實例 |
LinkedHashMap(int initialCapacity) | 構造具有指定初始容量和默認負載因子(0.75)的空插入有序LinkedHashMap實例 |
LinkedHashMap(int initialCapacity, float loadFactor) | 構造具有指定初始容量和負載因子的空插入有序LinkedHashMap實例 |
LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) | 構造具有指定初始容量、加載因子和排序模式的空LinkedHashMap實例 |
LinkedHashMap(Map<? extends K,? extends V> m) | 構造具有與指定映射相同映射的插入順序LinkedHashMap實例。 |
(2)常用方法
返回值 | 方法 | 作用 |
void | clear() | 從此映射中刪除所有映射。 |
boolean | containsValue(Object value) | 如果此映射將一個或多個鍵映射到指定值,則返回true。(如果存在value值,則返回true) |
V | get(Object key) | 返回指定鍵映射到的值,如果此映射不包含鍵的映射,則返回null |
protected boolean | removeEldestEntry(Map.Entry<K,V> eldest) | 如果此映射應刪除其最老項,則返回true(LRU,重寫該方法設置條件) |
(3)其他方法
其他方法諸如put、remove方法LinkedHashMap沒有重寫,所以可以通過調用父類HashMap的put、remove方法來實現。