1、原理

维护一个双向链表,最新访问或添加的元素插入到链表head或者tail,
假设采用尾插法,那么最新的元素都在尾部,当LRU缓存容量满的时候,就只需要把头部节点移除即可
当有查询操作,则根据key找到对应的node,并将node移到尾部,时间复杂度为O(1)
2、手写实现
package algo;import java.util.Hashtable;/*** TODO 此处填写class用途** @author weixin* @date 2020/5/9 16:25**/public class LRUCache {class DLinkedNode{int key;int value;DLinkedNode prev;DLinkedNode next;public DLinkedNode(){};public DLinkedNode(int key, int value){super();this.key = key;this.value = value;}@Overridepublic String toString() {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("DLinkedNode{ key=").append(key).append(", value=").append(value).append(", prev=").append(prev == null ? null : prev.key).append(", next=").append(next == null ? null : next.key);return stringBuilder.toString();}}/*** 缓存当前大小*/private int size;/*** 缓存容量*/private int capacity;private DLinkedNode head;private DLinkedNode tail;private Hashtable<Integer,DLinkedNode> cache;public LRUCache(int capacity) {this.size = 0;this.capacity = capacity;head = new DLinkedNode();tail = new DLinkedNode();//构建一个双向链表head.next = tail;tail.prev = head;cache = new Hashtable<Integer, DLinkedNode>();}public int get(int key) {DLinkedNode node = cache.get(key);if(null == node){return -1;}//将node移到尾部move2Tail(node);return node.value;}private void move2Tail(DLinkedNode node){node.next = tail;node.prev = tail.prev;tail.prev.next = node;tail.prev = node;}private void popNode(DLinkedNode node){System.out.println("removeNode: "+node);DLinkedNode second = node.next;head.next = second;second.prev = head;node.next = null;node.prev = null;}public void put(int key, int value) {DLinkedNode node = cache.get(key);//存在则覆盖if(node != null){node.value = value;cache.put(key,node);return;}size++;if(size>capacity){popNode(head.next);}//新增nodeDLinkedNode nNode = new DLinkedNode(key,value);addNode(nNode);cache.put(key,nNode);//超过容量,删除头部节点}private void addNode(DLinkedNode node){//添加到尾部tail.prev.next = node;node.prev = tail.prev;node.next= tail;tail.prev = node;System.out.println("add node: "+ node);}private void removeNode(DLinkedNode node){head.next = node.next;node.next.prev = head;node.next = null;node.prev = null;}public static void main(String[] args) {LRUCache lruCache = new LRUCache(4);for (int i = 1; i<10; i++) {lruCache.put(i,i);System.out.println(lruCache.get(i));}}}
