LRU:最近最少使用
标准的做法是使用双向链表+哈希表,这恰好是LinkedHashMap的底层实现
双向链表一端是最近使用的,新访问的值会放在这一端,如果访问的值原来就存在缓存中,会从原来的位置取出来,放在最近这一端
哈希表中是实际的存储
注意LinkedHashMap的构造方法参数accessOrder:
accessOrder为false,只有insert操作会改变双向链表节点位置
accessOrder为true,访问双向链表的节点,就会改变位置,get,put都可以
世界使用LinkedHashMap实现LRU如下:
public class LRUCache {
public static void main(String[] args) {
LRUCache cache = new LRUCache(2);
cache.put(1, 1);
cache.put(2, 2);
System.out.println(cache.get(1)); // 返回 1
cache.put(3, 3); // 该操作会使得关键字 2 作废
System.out.println(cache.get(2)); // 返回 -1 (未找到)
cache.put(4, 4); // 该操作会使得关键字 1 作废
System.out.println(cache.get(1)); // 返回 -1 (未找到)
System.out.println(cache.get(3)); // 返回 3
System.out.println(cache.get(4)); // 返回 4
}
Map<Integer, Integer> cache;
public LRUCache(int capacity) {
cache = new LruLinkedHashMap<>(capacity);
}
public void put(int key, int value) {
cache.put(key, value);
}
public Integer get(int key) {
if(!cache.containsKey(key)) {
return -1;
}
return cache.get(key);
}
@SuppressWarnings("serial")
private static class LruLinkedHashMap<K, V> extends LinkedHashMap<K, V> {
int capacity;
public LruLinkedHashMap(int capacity) {
super(16, 0.75f, true);
this.capacity = capacity;
}
@Override
protected boolean removeEldestEntry(Entry<K, V> eldest) {
return size() > capacity;
}
}
}