主要逻辑:
要有一个hashMap存储节点,实现o(1)的查找
要有一个双向链表,实现实现最近或刚添加的节点在头节点,
初始容量,每添加一个节点,就记录当前已添加的个数,如果添加之后已超过容量,则移除尾部的节点和hashMap里面的节点
java
public class LRUCacheDemo {
class LRUNode {
private int key;
private int value;
private LRUNode prev;
private LRUNode next;
public LRUNode() {
}
public LRUNode(int key, int value) {
this.key = key;
this.value = value;
}
}
private Map<Integer, LRUNode> cache = new HashMap<>();
private int capacity;
private int size;
private LRUNode head, tail;
public LRUCacheDemo(int capacity) {
this.capacity = capacity;
this.size = 0;
head = new LRUNode();
tail = new LRUNode();
head.next = tail;
tail.prev = head;
}
public int get(int key) {
LRUNode lruNode = cache.get(key);
if (lruNode == null) {
return -1;
}
moveNodeToHead(lruNode);
return lruNode.value;
}
public void put(int key, int value) {
// 从缓存中查询,如果存在,则更新value, 并把对应的node移到头部
LRUNode lruNode = cache.get(key);
if (lruNode != null) {
lruNode.value = value;
moveNodeToHead(lruNode);
} else {
// 如果不存在,则直接插入
// 放入hashMap
LRUNode node = new LRUNode(key, value);
cache.put(key, node);
// 添加到双向链表的头部
addToHead(node);
size++;
// 然后看容量是否超过了,如果超过了,则移除双向链表尾部的节点,并移除cache的节点
if (size > capacity) {
LRUNode tail = removeTail();
cache.remove(tail.key);
size--;
}
}
}
private LRUNode removeTail() {
LRUNode tail = this.tail.prev;
removeNode(tail);
return tail;
}
private void moveNodeToHead(LRUNode lruNode) {
removeNode(lruNode);
addToHead(lruNode);
}
private void addToHead(LRUNode lruNode) {
lruNode.prev = head;
lruNode.next = head.next;
head.next.prev = lruNode;
head.next = lruNode;
}
private void removeNode(LRUNode lruNode) {
lruNode.prev.next = lruNode.next;
lruNode.next.prev =lruNode.prev;
}
public static void main(String[] args) {
LRUCacheDemo lruCacheDemo = new LRUCacheDemo(2);
lruCacheDemo.put(1,1);
lruCacheDemo.put(2,2);
lruCacheDemo.get(2);
lruCacheDemo.put(3, 3);
lruCacheDemo.put(4, 4);
lruCacheDemo.get(1);
}
}