不用那么多花里胡哨,直接12行代码解决 /苦笑
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果密钥已经存在,则变更其数据值;如果密钥不存在,则插入该组「密钥/数据值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
进阶:
你是否可以在 O(1) 时间复杂度内完成这两种操作?。
示例:
LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 该操作会使得密钥 2 作废
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 该操作会使得密钥 1 作废
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4
首先写下LRU算法的理解:LRU即最久未使用淘汰策略,最常用于redis key-value 淘汰策略
在redis中使用一个队列来维护所有键值对集合,当一个key被get/put时这个键值对会被移动到最顶端,
这样末端的键值对就成了最久未使用的
java中实现这个队列最简单的方式还是使用双向链表实现,查询就需要用到Hash表了
最合适的数据结构,例如~~~~ LinkedHashMap
为什么选择它呢:
第一:Java中get/put/remove 时间复杂度达到 O(1)的就只有Map接口下面的实现类了
第二:LinkedHashMap是HashMap的子类并且它是有序的,那么这个队列就形成了
第三:该看看源码了,LinkedHashMap中有类似的相关方法的实现,
我们只需要继承并覆盖其中需要改动的部分就可以了
其作用就是在访问元素之后,将该元素放到双向链表的尾巴处
(所以这个函数只有在按照读取的顺序的时候才会执行),
建议大家去看看,如何优美的实现在双向链表中将指定元素放入链尾!
void afterNodeAccess(Node<K,V> p) { }
其作用就是在删除元素之后,将元素从双向链表中删除
void afterNodeRemoval(Node<K,V> p) { }
是否删除最久未使用节点
void afterNodeInsertion(boolean evict) { }
在插入新元素之后,需要回调函数判断是否需要移除一直不用的某些元素!
移除最近最少被访问条件之一,通过覆盖此方法可实现不同策略的缓存
LinkedHashMap是默认返回false的,我们可以继承LinkedHashMap然后复写该方法即可
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
题解: 由于继承了LinkedHashMap,并且不需要对put方法进行修改,所以不需要写put方法
class LRUCache extends LinkedHashMap<Integer, Integer>{
// 容器容量
private int capacity;
// 初始化LinkedHashMap设置初始容量和加载因子
public LRUCache(int capacity) {
super(capacity, 0.75F, true);
this.capacity = capacity;
}
// 修改get方法,当key-value不存在时返回-1
@Override
public int get(int key) {
return super.getOrDefault(key, -1);
}
// 修改回调方法,返回true时会删除末尾节点,所以用size和容量比较
@Override
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
return size() > capacity;
}
}
这个故事告诉我们,一定要多看源码!!!
其实redis中还有一个LRU的升级版,使用两个缓存队列,就不在这里扯了,感兴趣的可以去搜一搜。
参考作者:jeromememory
链接:https://leetcode-cn.com/problems/lru-cache/solution/yuan-yu-linkedhashmapyuan-ma-by-jeromememory/