1. 程式人生 > >常見面試題之作業系統中的LRU快取機制實現

常見面試題之作業系統中的LRU快取機制實現

LRU快取機制,全稱Least Recently Used,字面意思就是最近最少使用,是一種快取淘汰策略。換句話說,**LRU機制就是認為最近使用的資料是有用的,很久沒用過的資料是無用的,當記憶體滿了就優先刪除很久沒有使用的資料**。 基於LeetCode146,可以使用**雜湊連結串列**或者**自定義雙端連結串列類+雜湊表**兩種方法來實現LRU快取機制。 它應該支援以下操作:獲取資料`get`和 寫入資料`put`。 獲取資料`get(key)`:如果金鑰 (key) 存在於快取中,則獲取金鑰的值(總是正數),否則返回`-1`。 寫入資料`put(key, value)`:如果金鑰不存在,則寫入其資料值。當快取容量達到上限時,它應該在寫入新資料之前刪除最近最少使用的資料值,從而為新的資料值留出空間。 ### 1. 基於LinkedHashMap實現LRU快取機制 ```java class LRUCache { Map map; int capacity; public LRUCache(int capacity) { this.capacity = capacity; map = new LinkedHashMap<>(); } public int get(int key) { // 若key不存在返回-1 if(!map.containsKey(key)) return -1; // 若key存在則獲取key對應的val int val = map.get(key); // 更新位置 put(key, val); return val; } public void put(int key, int val) { // 若快取命中則先刪除資料在重新放入以更新位置 if(map.containsKey(key)) { map.remove(key); map.put(key, val); } else { // 若快取未命中則先判斷是否達到最大容量 // 超出容量則刪除最久沒有使用的資料(利用迭代器刪除第一個) if (capacity == map.size()) map.remove(map.keySet().iterator().next()); // 刪除完成後存放新資料 map.put(key, val); } } } ``` ### 2. 基於DoubleList與HashMap實現LRU快取機制 如果不使用LinkedHashMap,可以自己造輪子,自定義`DoubleList`類並結合`HashMap`實現與LinkedHashMap相同的功能。 ```java class LRUCache { int capacity; DoubleList cache; Map map; public LRUCache(int capacity) { this.capacity = capacity; cache = new DoubleList(); map = new HashMap<>(); } public int get(int key) { if(!map.containsKey(key)) return -1; int val = map.get(key).val; put(key, val); return val; } public void put(int key, int val) { Node node = new Node(key, val); if(map.containsKey(key)) { cache.remove(map.get(key)); cache.addFirst(node); map.put(key, node); } else { if(capacity == cache.size) map.remove(cache.removeLast().key); cache.addFirst(node); map.put(key, node); } } } class DoubleList { Node head, tail; int size; public DoubleList() { head = new Node(0, 0); tail = new Node(0, 0); head.next = tail; tail.prev = head; size = 0; } public void addFirst(Node node) { Node temp = head.next; node.next = temp; temp.prev = node; head.next = node; node.prev = head; size++; } public void remove(Node node) { Node temp = node.prev; temp.next = node.next; temp.next.prev = temp; size--; } public Node removeLast() { if (size == 0) return null; Node del = tail.prev; remove(del); return del; } } class Node { int key, val; Node prev, next; public Node(int key, int val) { this.key = key; this.val = val;