LRU-缓存
题目:
代码如下:
import java.util.HashMap;
/**
* LRU
* 节点为 Node<K, V>
*/
public class Code_02_LRU2 {
public static class Node<K, V> {
public K key;
public V value;
public Node<K, V> last;
public Node<K, V> next;
public Node(K key, V value) {
this.key = key;
this.value = value;
}
}
public static class NodeDoubleLinkedList<K, V> {
private Node<K, V> head;
private Node<K, V> tail;
public NodeDoubleLinkedList() {
this.head = null;
this.tail = null;
}
/**
* 在双向链表的尾巴上添加一个新的节点
* @param newNode 新的待添加到双向链表尾巴上的节点
*/
public void addNode(Node<K, V> newNode) {
if (newNode == null) {
return;
}
if (this.head == null) {
this.head = newNode;
this.tail = newNode;
} else {
this.tail.next = newNode;
newNode.last = this.tail;
this.tail = newNode;
}
}
/**
* 潜台词:双向链表上一定有这个node
* @param node 将这个node从双向链表上分离出去,然后接在双向链表的尾巴上
*/
public void moveNodeToTail(Node<K, V> node) {
if (this.tail == node) {
return;
}
if (this.head == node) { // 当前node是头节点
this.head = node.next;
this.head.last = null;
} else { // 当前node是中间的节点
node.last.next = node.next;
node.next.last = node.last;
}
node.last = this.tail;
node.next = null;
this.tail.next = node;
this.tail = node;
}
/**
* 移除头节点
* @return 移除掉的头节点
*/
public Node<K, V> removeHead() {
if (this.head == null) {
return null;
}
Node<K, V> res = this.head;
if (this.head == this.tail) {
this.head = null;
this.tail = null;
} else {
this.head = res.next;
res.next = null;
this.head.last = null;
}
return res;
}
}
public static class MyCache<K, V> {
private HashMap<K, Node<K, V>> keyNodeMap;
private NodeDoubleLinkedList<K, V> nodeList;
private int capacity;
public MyCache(int capacity) {
if (capacity < 1) {
throw new RuntimeException("should be more than 0.");
}
this.keyNodeMap = new HashMap<>();
this.nodeList = new NodeDoubleLinkedList<>();
this.capacity = capacity;
}
public V get(K key) {
if (this.keyNodeMap.containsKey(key)) {
Node<K, V> res = this.keyNodeMap.get(key);
this.nodeList.moveNodeToTail(res);
return res.value;
}
return null;
}
public void set(K key, V value) {
if (this.keyNodeMap.containsKey(key)) {
Node<K, V> node = this.keyNodeMap.get(key);
node.value = value;
this.nodeList.moveNodeToTail(node);
} else {
Node<K, V> newNode = new Node<>(key, value);
this.keyNodeMap.put(key, newNode);
this.nodeList.addNode(newNode);
if (this.keyNodeMap.size() == this.capacity + 1) {
this.removeMostUnusedCache();
}
}
}
private void removeMostUnusedCache() {
Node<K, V> removeNode = this.nodeList.removeHead();
this.keyNodeMap.remove(removeNode.key);
}
}
public static void main(String[] args) {
MyCache<String, Integer> testCache = new MyCache<>(3);
// A B C
testCache.set("A", 1);
testCache.set("B", 2);
testCache.set("C", 3);
// A C B
System.out.println(testCache.get("B"));
// C B A
System.out.println(testCache.get("A"));
// B A D
testCache.set("D", 4);
// B A D
System.out.println(testCache.get("D"));
System.out.println(testCache.get("C"));
}
}