Least Recently Use
LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
- 什么是LRU
- LRU的最简单实现
- 手写LRU
什么是LRU
距离现在最早使用的会被我们替换掉。不够形象的话我们看下面的例子。
插入 | 1 | 2 | 3 | 4 | 2 | 3 | 1 |
---|---|---|---|---|---|---|---|
位置1 | 1 | 1 | 1 | 2 | 3 | 4 | 2 |
位置2 | null | 2 | 2 | 3 | 4 | 2 | 3 |
位置3 | null | null | 3 | 4 | 2 | 3 | 1 |
…
位置1始终是最早进来的元素,是淘汰位置。新进来的元素如果是新元素直接放在位置3,然后将位置1弹出。如果是已有元素则将其放在位置3并删除之前位置上的已有元素,保持其他元素相对位置不变。
这里的例子就是一个size=3的缓存淘汰实现。
利用LinkedHashMap实现的简单LRU
对于
java.util.LinkedHashMap
我们的认识仅仅只是停留在该map可以按照插入的顺序保存,那是不够的。
linkedHashMap还可以实现按照访问顺序保存元素。
先看看如何利用它实现LRU的吧
public class UseLinkedHashMapCache<K,V> extends LinkedHashMap<K,V>{
private int cacheSize;
public UseLinkedHashMapCache(int cacheSize){
//构造函数一定要放在第一行
super(16,0.75f,true); //那个f如果不加 就是double类型,然后该构造没有该类型的入参。 然后最为关键的就是那个入参 true
this.cacheSize = cacheSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K,V> eldest){ //重写LinkedHashMap原方法
return size()>cacheSize; //临界条件不能有等于,否则会让缓存尺寸小1
}
}
关键点:
- 继承了LinkedHashMap并使用
-
public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) { super(initialCapacity, loadFactor); this.accessOrder = accessOrder; }
构造函数
- 重写了
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) { return false; }
看看如何使用
public static void main(String[]args){
UseLinkedHashMapCache<Integer,String> cache = new UseLinkedHashMapCache<Integer,String>(4);
cache.put(1, "one");
cache.put(2, "two");
cache.put(3, "three");
cache.put(4, "four");
cache.put(2, "two");
cache.put(3, "three");
Iterator<Map.Entry<Integer,String>> it = cache.entrySet().iterator();
while(it.hasNext()){
Map.Entry<Integer, String> entry = it.next();
Integer key = entry.getKey();
System.out.print("Key:\t"+key);
String Value = entry.getValue(); //这个无需打印...
System.out.println();
}
}
结果是:
Key: 1
Key: 4
Key: 2
Key: 3
与我们表格中的结果一致。