1. 程式人生 > >【面試題】LRU算法及編碼實現LRU策略緩存

【面試題】LRU算法及編碼實現LRU策略緩存

max 防止 技術分享 nbsp pri value 概念 閾值 使用

概念

  LRU(least recently used)就是將最近不被訪問的數據給淘汰掉,LRU基於一種假設:認為最近使用過的數據將來被使用的概率也大,最近沒有被訪問的數據將來被使用的概率比較低。

原理

  LRU一般通過鏈表形式來存放緩存數據,新插入或被訪問的數據放在鏈表頭部,超過一定閾值後,自動淘汰鏈表尾部的數據。下圖很形象的說明了LRU緩存淘汰過程。(圖片來自網絡)

技術分享圖片

步驟:

1、新插入A, 將A放置在隊列頭部

2、新插入B, 將B放置在隊列頭部, A自動推舉次席。

3、新插入C, 將C放置在隊列頭部, B自動推舉次席。

4、新插入D, 將D放置在隊列頭部, C自動推舉次席。

5、新插入E, 將E放置在隊列頭部, D自動推舉次席。

6、新插入E, 將E放置在隊列頭部, 這時隊列長度大於閾值,自動將尾部數據A給淘汰掉

7、訪問數據C,然後將C重新放置在隊列頭部。

8、新插入E, 將E放置在隊列頭部, 這時隊列長度大於閾值,自動淘汰尾部數據B

編碼實現LRU策略緩存

/**
 * Created by zhuhezan on 2018/4/11.
 *
 * 使用鏈表+hashmap來實現, 這裏沒有考慮並發情況, 所以在代碼中沒有使用鎖
 */
public class LRUCache<K, V> {

    class CacheNode {
        public CacheNode before;
        
public Object key; public Object value; public CacheNode after; public CacheNode() { } } private HashMap<K, CacheNode> caches; private int maxCapacity; private int currentCacheSize; /** * 頭結點, 頭結點不參與淘汰,只是作為標識鏈表中的第一個節點 */ private
CacheNode head; /** * 尾節點, 尾節點不參與淘汰, 只是作為標識鏈表中最後一個節點 */ private CacheNode tail; public LRUCache(int maxCapacity) { this.maxCapacity = maxCapacity; caches = new HashMap<>(maxCapacity); head = tail = new CacheNode(); head.after = tail; //對head 的after節點賦值, 防止後續操作出現空指針異常 tail.before = head; // 對tail的before節點賦值, 防止後續操作出現空指針異常 } public void put(K k, V v) { CacheNode node = caches.get(k); if (node == null) { if (currentCacheSize >= maxCapacity) { caches.remove(tail.before.key); //淘汰尾部的元素 removeLast(); } node = new CacheNode(); node.key = k; currentCacheSize ++; } node.value = v; moveToFirst(node); // LRU策略, 新插入的元素放置到隊列頭部 caches.put(k, node); } public void moveToFirst(CacheNode node) { CacheNode n = head.after; head.after = node; node.before = head; n.before = node; node.after = n; } public void removeLast() { CacheNode n = tail.before.before; n.after = tail; tail.before = n; } public Object get(K k) { CacheNode node = caches.get(k); if (node == null) { return null; } Object v = node.value; moveToFirst(node); return v; } public Object remove(K k) { CacheNode node = caches.get(k); if (node == null) { return null; } CacheNode pre = node.before; CacheNode next = node.after; pre.after = next; next.before = pre; caches.remove(k); currentCacheSize --; return node.value; } }

上述代碼在博主本機測試驗證通過(單線程操作下)

【面試題】LRU算法及編碼實現LRU策略緩存