一 什么是LRU
全称Least Recently Used ,当数据所占内存达到一定阈值,我们要移除掉最近最少使用的数据。
二 实现LRU
1.通过LinkedHashMap来实现
为了实现缓存回收,我们需要做到以下两点:
- 查询出最近最晚使用的项
- 给最近使用的项做一个标记
JAVA中实现LRU最简单的方法是利用LinkedHashMap,其中的核心是重写removeEldestEntry(Map.Entry)方法。
为什么使用LinkedHashMap呢?
GET方法:
public V get(Object key) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null)
return null;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}
当accessOrder是true的时候,afterNodeAccess(e)都要将元素移动到尾部,所以要保证access是true
我们再看LinkedHashMap的构造函数:
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
我们再看LinkedHashMap的removeEldestEntry,核心就是重写这个方法:
LinkedHashMap会在每次有新元素加入的时候,判断当前储存元素是否超过了缓存上限,也就是执行
一次removeEldestEntry方法
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
实现
import java.util.*;
//扩展一下LinkedHashMap这个类,让他实现LRU算法
class LRULinkedHashMap<K,V> extends LinkedHashMap<K,V>{
//定义缓存的容量
private int capacity;
private static final long serialVersionUID = 1L;
//带参数的构造器
LRULinkedHashMap(int capacity){
//调用LinkedHashMap的构造器,传入以下参数
super(16,0.75f,true);
//传入指定的缓存最大容量
this.capacity=capacity;
}
//实现LRU的关键方法,如果map里面的元素个数大于了缓存最大容量,则删除链表的顶端元素
@Override
public boolean removeEldestEntry(Map.Entry<K, V> eldest){
System.out.println(eldest.getKey() + "=" + eldest.getValue());
return size()>capacity;
}
}
//测试类
class Test{
public static void main(String[] args) throws Exception{
//指定缓存最大容量为4
Map<Integer,Integer> map=new LRULinkedHashMap<>(4);
map.put(9,3);
map.put(7,4);
map.put(5,9);
map.put(3,4);
map.put(6,6);
//总共put了5个元素,超过了指定的缓存最大容量
//遍历结果
for(Iterator<Map.Entry<Integer,Integer>> it=map.entrySet().iterator();it.hasNext();){
System.out.println(it.next().getKey());
}
}
}
输出:
9=3
9=3
9=3
9=3
9=3
7
5
3
6