解题思路
通过HashMap和双向链表来实现LRU缓存。
首先,初始化的时候应该设置好当前缓存的容量,并且初始化当前的双向链表。
然后,get方法需要先判断这个元素存不存在,如果存在,还需要更新链表里面这个节点的位置,把它移到链表尾部。
然后,put方法首先需要判断这个元素的key存不存在,存在的话就移除原来的这个节点,重新加入这个节点;不存在的话,需要判断当前的size是否大于等于容量,如果是,需要更新缓存,删除链表的头结点,然后在尾部插入新节点。
代码
import java.util.HashMap;
import java.util.Map;
/**
* @Auther: Bai
* Description: JavaStudy
* Created in 2022/07/30 19:30
*/
public class LRUCache {
//链表节点类
class Node {
int key = 0;
int val = 0;
Node next = null;
Node pre = null;
public Node() {
}
public Node(int key, int val, Node next, Node pre) {
this.key = key;
this.val = val;
this.next = next;
this.pre = pre;
}
}
int capacity = 0;
Map<Integer, Node> map = new HashMap<>();
Node head = new Node();
Node tail = new Node();
public LRUCache(int capacity) {
this.capacity = capacity;
head.next = tail;
tail.pre = head;
}
public int get(int key) {
//判断存不存在
if (!map.containsKey(key)) return -1;
Node node = map.get(key);
moveToTail(node);
return node.val;
}
//添加一个元素
public void put(int key, int value) {
//判断该元素的key存不存在
if (map.containsKey(key)) {
removeNode(key);
addNode(key,value);
return;
}
//判断需不需要更新缓存
if (map.size() >= capacity) {
removeNode(-1);
}
addNode(key, value);
}
//把一个节点移动到链表尾部
private void moveToTail(Node node) {
node.pre.next = node.next;
node.next.pre=node.pre;
node.pre = tail.pre;
node.next = tail;
tail.pre.next=node;
tail.pre = node;
}
//删除某个元素,key为-1表示删除头元素,否则正常删除
private void removeNode(int key) {
Node re = null;
if (key == -1) {
re = head.next;
head.next = re.next;
head.next.pre = head;
} else {
re = map.get(key);
re.pre.next = re.next;
re.next.pre = re.pre;
}
map.remove(re.key);
}
//添加一个元素
private void addNode(int key, int val) {
Node node = new Node(key, val, this.tail, this.tail.pre);
tail.pre = node;
node.pre.next=node;
map.put(key, node);
}
}