原理
LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
链表:有序的集合。
思想:最近使用的数据移至链表头部,链表满时将尾部数据删除。
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
public class Test {
public static void main(String[] args) {
LruMap<String, Integer> lm = new LruMap<>(4);
lm.put("2", 2);
lm.put("1", 1);
lm.put("3", 3);
lm.put("5", 5);
System.out.println(lm.toString());
System.out.println(lm.get("1"));
System.out.println(lm.toString());
System.out.println(lm.put("4", 4));
System.out.println(lm.toString());
System.out.println(lm.put("6", 6));
System.out.println(lm.toString());
//打印结果
/*
{2=2, 1=1, 3=3, 5=5}
1
{2=2, 3=3, 5=5, 1=1}
4
{3=3, 5=5, 1=1, 4=4}
6
{5=5, 1=1, 4=4, 6=6}
*/
}
static class LruMap<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 1L;
private Map<K, V> lmp = new LinkedHashMap<>();
private int cap;
public LruMap(int cap) {
this.cap = cap;
}
public V get(Object key) {
// 最近使用的数据移至链表头部
moveHead(key);
return lmp.get(key);
}
public V put(K key, V value) {
if (cap == lmp.size()) {
// 移除最久的数据
move();
}
lmp.put(key, value);
return value;
}
private void move() {
Set<Entry<K, V>> set = lmp.entrySet();
int i = 0;
Map<K, V> temp = new LinkedHashMap<>();
for (Entry<K, V> entry : set) {
// 移除最久的,即第一个,越新的数据越排在后面
if (i != 0) {
temp.put(entry.getKey(), entry.getValue());
}
i++;
}
lmp = temp;
}
private void moveHead(Object key) {
Set<Entry<K, V>> set = lmp.entrySet();
Map<K, V> temp = new LinkedHashMap<>();
Object value = null;
for (Entry<K, V> entry : set) {
if (!key.equals(entry.getKey())) {
temp.put(entry.getKey(), entry.getValue());
} else {
value = entry.getValue();
}
}
// 头部即最后一个put进去,最新
temp.put((K) key, (V) value);
lmp = temp;
}
public String toString() {
return lmp.toString();
}
}
}