面试题LRU算法及编码实现LRU策略缓存
Posted jsnr-tdyd
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试题LRU算法及编码实现LRU策略缓存相关的知识,希望对你有一定的参考价值。
概念
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策略缓存的主要内容,如果未能解决你的问题,请参考以下文章