LRU算法
LRU算法
package com.redis;
import java.util.HashMap;
import java.util.Map;
/**
* LRU缓存实现
* 使用哈希表+双向链表实现O(1)时间复杂度的get和put操作
*/
public class LRUCache {
// 头部和尾部节点
private Entry head, tail;
// 当前缓存大小
private int size;
// 缓存容量
private int capacity;
// 哈希表用于快速查找
private Map<Integer, Entry> cache;
// 双向链表节点类
public static class Entry{
int key;
int value;
Entry prev;
Entry next;
public Entry(int key, int value) {
this.key = key;
this.value = value;
}
public Entry() {
}
}
/**
* 构造函数初始化LRU缓存
* @param capacity 缓存容量
*/
public LRUCache(int capacity) {
this.capacity = capacity;
// 初始化链表
initLinkedList();
this.size = 0;
cache = new HashMap <>(capacity + 2);
}
// 初始化链表
private void initLinkedList() {
head = new Entry();
tail = new Entry();
head.next = tail;
tail.prev = head;
}
/**
* 获取缓存值,如果不存在则返回-1,否则将节点移动到头节点,并返回节点数据
* @param key 键
* @return 如果key存在返回对应的value
*/
public int get(int key) {
Entry nodo = cache.get(key);
if(nodo == null){
return -1;
}
moveToHead(nodo);
return nodo.value;
}
/**
* 添加或更新缓存
* @param key 键
* @param value 值
*/
public void put(int key, int value) {
Entry node = cache.get(key);
if(node != null){
node.value = value;
moveToHead(node);
return;
}
// 不存在,先加进去,再移除尾节点
// 此时容量已满,删除尾节点
if(size == capacity){
Entry lastNode = tail.prev;
// 从链表中删除尾节点
deleteNode(lastNode);
// 从缓存中删除尾节点
cache.remove(lastNode.key);
size--;
}
// 将新的节点放置head节点的后面
Entry newNode = new Entry();
newNode.key = key;
newNode.value = value;
addToHead(newNode);
cache.put(key,newNode);
size ++;
}
/**
* 移动节点到链表头部
* @param node 要移动的节点
*/
private void moveToHead(Entry node) {
// 首先删除原来节点的关系
deleteNode(node);
// 将原来节点放置head节点的后面
addToHead(node);
}
private void addToHead(Entry node) {
node.prev = head; // 新节点的prex--->指向head
node.next = head.next; // 新节点的next--->指向原节点
head.next.prev = node; //原节点的prev--->指向新节点
head.next = node; // head的next---> 指向新节点
}
private void deleteNode(Entry node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
/**
* 打印当前缓存内容(用于调试)
*/
public void printCache() {
System.out.print("Cache: ");
Entry current = head.next;
while (current != tail) {
System.out.print("[" + current.key + "=" + current.value + "] ");
current = current.next;
}
System.out.println();
}
public static void main(String[] args) {
// 测试案例
LRUCache cache = new LRUCache(2);
cache.put(1,1);
cache.put(2,2);
cache.printCache(); //21
cache.get(1);
cache.printCache(); // 12
cache.put(3,3);
cache.printCache(); //31
System.out.println(cache.get(2)); // -1
}
}
执行结果