Java使用LinkedHashMap实现LRU缓存
参加拼多多一面的时候手撕了LRU,虽然我知道经常会考LRU,但是自己一直没动手去实现,这里介绍一下LRU以及Java实现
LRU介绍
LRU可以用来当作缓存,每次访问LRU的数据之后,那个数据将变成最新的。往里面添加数据后,若容量超过自己设置的最大容量,将会删除最老的数据。即最早添加的或最长时间未使用的(注意:最早的被访问也会变成最新的)
LRU实现方式
Java实现LRU一般采用链表+HashMap的形式,链表维护顺序,HashMap便于快速查找数据,而不用去遍历链表
- LinkedHashMap支持LRU,其本质也是链表和HashMap,可以对其进行改造生成我们所需要的LRU
- 自己使用链表和HashMap生成LRU
这里我们首先介绍使用LinkedHashMap实现LRU
LinkedHashMap实现LRU
import java.util.LinkedHashMap;
import java.util.Map;
public class LRU<K, V> {
/**
* The head (eldest) of the doubly linked list.
*/
//transient LinkedHashMap.Entry<K,V> head;
//LinkedHashMap最前面是最旧的
//这里设置LinkedHashMap容量,负载因子使用默认的0.75
private final float loadFactory = 0.75f;
private LinkedHashMap<K, V> map;
public LRU(int maxCacheSize) {
//HashMap达到容量就进行扩容,if ((size >= threshold),因此需要+1
int capacity = (int)Math.ceil(maxCacheSize / this.loadFactory) + 1;
//public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder),accessOrder为true表示LRU
map = new LinkedHashMap<K, V>(capacity, loadFactory, true) {
//重写removeEldestEntry,当容量超过maxCacheSize会移除first
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > maxCacheSize;
}
};
}
public void put(K key, V value) {
map.put(key, value);
}
public V get(K key) {
return map.get(key);
}
public void remove(K key) {
map.remove(key);
}
public boolean contain(K key) {
return map.containsKey(key);
}
//还有一些其他方法可以自己去实现
public static void main(String[] args) {
LRU<Integer, Integer> lru = new LRU<Integer, Integer>(2);
lru.put(1, 1);
lru.put(2, 2);
//key = 1会被移除,最旧的
lru.put(3, 3);
lru.put(2, 3);
System.out.println("lru包含key为1的: " + lru.contain(2));
System.out.println("lru包含key为3的: " + lru.contain(3));
//key = 3会被移除,因为刚才重置了2的值,2变成最新的了
lru.put(1, 3);
System.out.println("lru包含key为3的: " + lru.contain(3));
}
}
运行结果
lru包含key为1的: true
lru包含key为3的: true
lru包含key为3的: false
Process finished with exit code 0
下一篇我们介绍一下自己使用链表和HashMap实现LRU