Java LinkedHashMap 实现 LRU
- LinkedHashMap 有两种使用模式:insert-order 和 access-order。通过指定构造方法accessOrder参数来决定使用哪种模式
/**
* Constructs an empty <tt>LinkedHashMap</tt> instance with the
* specified initial capacity, load factor and ordering mode.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @param accessOrder the ordering mode - <tt>true</tt> for
* access-order, <tt>false</tt> for insertion-order
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
- insert-order 在迭代 LinkedHashMap 时,会按插入的顺序依次访问 key value。
- access-order 则表示将 LinkedHashMap 作为 LRU 缓存来使用,也即:
- get(key) 访问缓存中的元素时,需要记录下来,表明此 key 是最近被访问过的,作为后面淘汰 key 的依据。
- 在淘汰缓存中的元素时,最久未被访问的 key 需要被删除。这通过:继承 removeEldestEntry 方法来实现。
实现 LRUCache 类:
- LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存。缓存需要一个容量,当缓存中的元素超过此容量时,执行汰换。
- 可用过 size() 方法获取缓存当前的元素个数。
java.util.HashMap#size
- int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
- void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。
import java.util.*;
class LRUCache<K,V> extends LinkedHashMap<Integer, Integer>{
private int capacity;//缓存需要一个容量,当缓存中的元素超过此容量时,执行汰换。
public LRUCache(int capacity) {
//true 表示 创建 LinkedHashMap 时, 采用: access-order(false 时为:insertion-order)
super(capacity,0.75f,true);
this.capacity = capacity;
}
public int get(int key) {
//如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
Integer value = super.getOrDefault(key, -1);
return value;
}
public void put(int key, int value) {
super.put(key, value);
}
@Override
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
//缓存中的元素大于 capacity 时,执行汰换。在 put 操作时,会自动调用此方法,删除最久未被访问的key
return size() > capacity ;
}
}
LinkedHashMap
public class Test {
public static void main(String[] args) {
//access order 为 true,可以用作lru,创建 LinkedHashMap 时,access order 默认为 false,也即采用的是 insert order,元素插入的顺序
LinkedHashMap<String, Integer> lru = new LinkedHashMap<>(20, 0.75f, false);
LinkedHashMap<String, Integer> insertMap = new LinkedHashMap<>();
// LinkedHashMap<String, Integer> insertMap = new LinkedHashMap<>(20, 0.75f, true);
insertMap.put("c", 3);
insertMap.put("a", 1);
insertMap.put("b", 2);
for (Map.Entry<String, Integer> entry : insertMap.entrySet()) {
//key=c value=3
//key=a value=1
//key=b value=2
System.out.println("key=" + entry.getKey() + " value=" + entry.getValue());
}
}
}