Java 实现 LRUCache
-
双向链表+HashMap
-
使用双向链表的原因:删除链表特定节点(将某个节点移动到链表头部 或 删除 尾节点都需要用到)需要获得其前驱,要在O(1)时间复杂度内完成则可使用双向链表
-
使用双向链表存key 和 value :删除链表尾节点时,也需要删除HashMap对应记录,需要用到key,
cache.remove(tail.key)
public class MyLRUCache {
class Node {
private int key;
private int value;
private Node prev;
private Node next;
public Node() {
}
public Node(int key, int value) {
this.key = key;
this.value = value;
}
}
private int capacity;
private int size;
private Map<Integer, Node> cache = new HashMap<>();
private Node head, tail;
public MyLRUCache(int capacity) {
this.size = 0;
this.capacity = capacity;
head = new Node();
tail = new Node();
head.next = tail;
tail.prev = head;
}
public void put(int key, int value) {
Node node = cache.get(key);
if (node != null) {
node.value = value;
deleteNode(node);
addToHead(node);
} else {
Node newNode = new Node(key, value);
cache.put(key, newNode);
addToHead(newNode);
size++;
if (size > capacity) {
Node tail = deleteTail();
cache.remove(tail.key);
size--;
}
}
}
private Node deleteTail() {
Node last = tail.prev;
deleteNode(last);
return last;
}
public int get(int key) {
Node node = cache.get(key);
if (node == null) {
return -1;
}
deleteNode(node);
addToHead(node);
return node.value;
}
private void addToHead(Node node) {
node.prev = head;
node.next = head.next;
head.next.prev = node;
head.next = node;
}
private void deleteNode(Node node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
}