手写LRU 缓存
主要逻辑:
要有一个hashMap存储节点,实现o(1)的查找
要有一个双向链表,实现实现最近或刚添加的节点在头节点,
初始容量,每添加一个节点,就记录当前已添加的个数,如果添加之后已超过容量,则移除尾部的节点和hashMap里面的节点
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 {// 如果不存在,则直接插入// 放入hashMapLRUNode 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);}
}
