一、使用LinkedHashMap实现
class LRUCache {
Map<Integer, Integer> cache=null;
public LRUCache(int capacity) {
cache = new LinkedHashMap<>(capacity, 0.75f, true){
@Override
public boolean removeEldestEntry(Map.Entry eldest){
if(this.size()>capacity){
return true;
}
return false;
}
};
}
public int get(int key) {
Integer v = this.cache.get(key);
return v==null?-1:v.intValue();
}
public void put(int key, int value) {
this.cache.put(key,value);
}
}
二、使用HashMap 和DoubleList 实现
class LRUCache {
int capacity;
DoubleList cache;
Map<Integer, Node> map;
public LRUCache(int capacity) {
this.capacity = capacity;
cache = new DoubleList();
map = new HashMap<>();
}
public int get(int key) {
if(!map.containsKey(key)){
return -1;
}
Node tmp = map.get(key);
cache.remove(tmp);
cache.addFirst(tmp);
return tmp.value;
}
public void put(int key, int value) {
Node cur = new Node(key, value);
if(map.containsKey(key)){
cache.remove(map.get(key));
cache.addFirst(cur);
map.put(key, cur);
}else{
if(capacity == cache.size){
Node del = cache.removeLast();
map.remove(del.key);
}
map.put(key, cur);
cache.addFirst(cur);
}
}
class DoubleList{
Node head, tail;
int size; //链表的长度
public DoubleList(){
head = new Node(0, 0);
tail = new Node(0, 0);
head.next = tail;
tail.pre = head;
size = 0;
}
在链表头部添加节点 x, 时间 O(1)
public void addFirst(Node cur){
Node next = head.next;
cur.next = next;
next.pre = cur;
head.next = cur;
cur.pre = head;
size++;
}
// 删除链表中的 x 节点(x ⼀定存在)
// 由于是双链表且给的是⽬标 Node 节点, 时间 O(1)
public void remove(Node node){
Node prev = node.pre;
prev.next = node.next;
prev.next.pre = prev;
size--;
}
// 删除链表中最后⼀个节点, 并返回该节点, 时间 O(1)
public Node removeLast(){
if(size == 0)
return null;
Node del = tail.pre;
remove(del);
return del;
}
}
class Node{
int key ,value;
Node pre, next;
public Node(int key, int value){
this.key = key;
this.value = value;
}
}
public static void main(String[] args){
/* 缓存容量为 2 */
LRUCache cache = new LRUCache(2);
// 你可以把 cache 理解成⼀个队列
// 假设左边是队头, 右边是队尾
// 最近使⽤的排在队头, 久未使⽤的排在队尾
// 圆括号表⽰键值对 (key, val)
cache.put(1, 1);
// cache = [(1, 1)]
cache.put(2, 2);
// cache = [(2, 2), (1, 1)]
cache.get(1); // 返回 1
// cache = [(1, 1), (2, 2)]
// 解释: 因为最近访问了键 1, 所以提前⾄队头
// 返回键 1 对应的值 1
cache.put(3, 3);
// cache = [(3, 3), (1, 1)]
// 解释: 缓存容量已满, 需要删除内容空出位置
// 优先删除久未使⽤的数据, 也就是队尾的数据
// 然后把新的数据插⼊队头
cache.get(2); // 返回 -1 (未找到)
// cache = [(3, 3), (1, 1)]
// 解释: cache 中不存在键为 2 的数据
cache.put(1, 4);
// cache = [(1, 4), (3, 3)]
// 解释: 键 1 已存在, 把原始值 1 覆盖为 4
// 不要忘了也要将键值对提前到队头
}
}
/**
* 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);
*/