简介
LRU(Least Recently Used)算法,是一种常用的缓存淘汰策略,优先淘汰最近最少使用的对象。一般通过双向链表和hash表实现。
代码
import java.util.HashMap;
import java.util.Map;
/**
* LRU:内存不足,进行数据淘汰时优先淘汰最近最少使用的数据。
* 本次实现思路:
* 1. 使用map存储数据
* 2. 使用双向链表保证数据顺序性,决定数据淘汰顺序
*/
public class Lru<K, V> {
//定义节点,存储键值对数据
private static class ListNode<K, V> {
private K key;
private V value;
private ListNode<K, V> prev;
private ListNode<K, V> next;
public ListNode(K key, V value) {
this.key = key;
this.value = value;
}
}
//最大容量
private final int maxCap;
//存储数据
private final Map<K, ListNode<K, V>> map;
//链表头部节点,用于将最新访问的放入头部
private final ListNode<K, V> head = new ListNode<>(null, null);
//链表尾部,用于淘汰数据
private final ListNode<K, V> tail = new ListNode<>(null, null);
public Lru(int maxCap) {
this.maxCap = maxCap;
map = new HashMap<>(maxCap);
head.next = tail;
tail.prev = head;
}
//添加数据时将数据放入节点头部
private void add(ListNode<K, V> node) {
node.next = head.next;
node.prev = head;
head.next.prev = node;
head.next = node;
}
//从链表中移除节点
private void remove(ListNode<K, V> node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
//插入数据
public V put(K key, V value) {
if (map.containsKey(key)) {
ListNode<K, V> node = map.get(key);
V old = node.value;
node.value = value;
remove(node);
add(node);
return old;
}
//不存在,超限淘汰数据
if (map.size() >= maxCap) {
map.remove(tail.prev.key);
remove(tail.prev);
}
ListNode<K, V> node = new ListNode<>(key, value);
map.put(key, node);
add(node);
return null;
}
}