LRU(Least recently used,最近未使用算法) 算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
链表(处理新老关系)+ 哈希(查询在不在) 整体时间复杂度可以达到O(1)
import lombok.Data;
import java.util.HashMap;
public class LRUCache {
int capacity;
HashMap<Integer, Node> map; 时间复杂度O(1),找到对应Node节点
Node head;//满了 需要删除的节点
Node end; //为最近使用的数据
//这个初始化非常重要 省的处理head end节点为null
public LRUCache(int capacity) {
this.capacity = capacity;
map = new HashMap<>();
head = new Node(-1, -1);
end = new Node(-1, -1);
head.next = end;
end.pre = head;
}
public void put(int key, int value) {
// 调用get方法 如果存在则会
if (get(key) != -1) {
map.get(key).value = value;
return;
}
//如果不存在,新增一个节点,放到end节点
Node node = new Node(key, value);
map.put(key, node);
moveToEnd(node);
if (map.size() > capacity) {
map.remove(head.next.key);
head.next = head.next.next;
head.next.pre = head;
}
}
public int get(int key) {
if (!map.containsKey(key)) {
return -1;
}
Node node = map.get(key);
// 删除该节点,需要两步
node.pre.next = node.next;
node.next.pre = node.pre;
moveToEnd(node);
return node.value;
}
//移动节点到end前,需要四步
private void moveToEnd(Node node) {
node.pre = end.pre;
end.pre = node;
node.pre.next = node;
node.next = end;
}
@Data
class Node {
int key;
int value;
Node pre;
Node next;
public Node(int key, int value) {
this.key = key;
this.value = value;
}
}
public static void main(String[] args) {
LRUCache lru = new LRUCache(3);
lru.put(1, 1);
lru.put(2, 2);
lru.put(3, 3);
lru.put(4, 4);
lru.put(5, 5);
lru.get(1);
lru.put(1, 1);
}
PS:
HBSE的LRU缓存机制
ConcurrentHashMap来维护key-value,将最近最少使用的Block置换出来。