思路源自
【面试高频】146. LRU 缓存
采用哈希表+双向链表
put一个键值对时,采用头插法将缓存块置于等级较高的位置,如果put数量超出限制,那么就将尾部的缓存块删除,以此达到置换的一个效果
get一个键值对也是同样的思路,如果不命中直接返回-1,如果命中先删除缓存块再头插缓存块,这样就达到了访问后更新缓存块等级的目的
class LRUCache {
class DoubleLinkedNode {
DoubleLinkedNode pre;
int key;
int value;
DoubleLinkedNode next;
public DoubleLinkedNode() {
key=-1;
value=-1;
}
public DoubleLinkedNode(int key, int value) {
this.key=key;
this.value = value;
}
}
private int size;
private int capacity;
private Map<Integer,DoubleLinkedNode> cache;
DoubleLinkedNode head;
DoubleLinkedNode tail;
//初始化两个虚拟节点,头尾指针互指
public LRUCache(int capacity) {
this.size=0;
this.capacity=capacity;
this.cache = new HashMap<>();
this.head = new DoubleLinkedNode();
this.tail = new DoubleLinkedNode();
head.pre=null;
head.next=tail;
tail.pre=head;
tail.next = null;
}
//获取缓存中的值,如果命中要更新缓存
public int get(int key) {
if (cache.containsKey(key)) {
DoubleLinkedNode doubleLinkedNode = cache.get(key);
this.delete(doubleLinkedNode.key);
this.add(doubleLinkedNode.key, doubleLinkedNode.value);
return doubleLinkedNode.value;
} else {
return -1;
}
}
//缓存添加或者置换
public void put(int key, int value) {
if (cache.containsKey(key)) {
this.delete(key);
this.add(key, value);
} else {
if (this.capacity == this.size) {
this.delete(tail.pre.key);
}
this.add(key, value);
}
}
//新增一个新的缓存,采用头插法
private void add(int key, int value) {
DoubleLinkedNode doubleLinkedNode = new DoubleLinkedNode(key, value);
doubleLinkedNode.pre=this.head;
doubleLinkedNode.next=this.head.next;
this.head.next.pre=doubleLinkedNode;
this.head.next=doubleLinkedNode;
this.size++;
cache.put(key, doubleLinkedNode);
}
//删除一个现有缓存
private void delete(int key) {
DoubleLinkedNode doubleLinkedNode = cache.get(key);
doubleLinkedNode.pre.next=doubleLinkedNode.next;
doubleLinkedNode.next.pre = doubleLinkedNode.pre;
this.size--;
cache.remove(key);
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/