目录
- LRU 简介
- LinkedHashMap的使用
- 手写LRU缓存淘汰算法
LRU 简介
LRU 是 Least Recently Used 的缩写,这种算法认为最近使用的数据是热门数据,下一次很大概率将会再次被使用。而最近很少被使用的数据,很大概率下一次不再用到。当缓存容量的满时候,优先淘汰最近很少使用的数据。
假设现在缓存内部数据如图所示:
这里我们将列表第一个节点称为头结点,最后一个节点为尾结点。
当调用缓存获取 key=1 的数据,LRU 算法需要将 1 这个节点移动到头结点,其余节点不变
然后我们插入一个 key=8 节点,此时缓存容量到达上限,所以加入之前需要先删除数据。由于每次查询都会将数据移动到头结点,未被查询的数据就将会下沉到尾部节点,尾部的数据就可以认为是最少被访问的数据,所以删除尾结点的数据。
然后我们直接将数据添加到头结点。
这里总结一下 LRU 算法具体步骤:
- 新数据直接插入到列表头部
- 缓存数据被命中,将数据移动到列表头部
- 缓存已满的时候,移除列表尾部数据。
LinkedHashMap的使用
会把添加查找的元素放到尾结点,删除的会从头结点删除
public class Test01 {
public static void main(String[] args) {
LinkedHashMap<String,String> linkedHashMap
= new LinkedHashMap<>(16,0.75f,true);
linkedHashMap.put("a","a");
linkedHashMap.put("b","b");
linkedHashMap.put("c","c");
//acb
linkedHashMap.get("b");
//cba
linkedHashMap.get("a");
linkedHashMap.forEach((k,v)->{
System.out.println("k:"+k+","+v);
});
}
}
手写LRU缓存淘汰算法
public class LruCache<K,V> extends LinkedHashMap<K,V> {
/**
* 容量
*/
private int capacity;
public LruCache(int capacity){
super(capacity,0.75f,true);
this.capacity = capacity;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size()>capacity;
}
public static void main(String[] args) {
LruCache<String, String> lruCache = new LruCache<>(3);
lruCache.put("a","a");
lruCache.put("b","b");
lruCache.put("c","c");
lruCache.put("d","d");
lruCache.forEach((k,v)->{
System.out.println("k:"+k+","+v);
});
}
}