实现代码,惰性删除过期节点
import java.util.*;
public class LRUWithExpire {
static class ListNode{
int key;
int value;
//单位为毫秒
long expire;
ListNode pre;
ListNode next;
public ListNode(int key, int value, long expire){
this.key = key;
this.value = value;
this.expire = System.currentTimeMillis() + expire;
}
public ListNode(){}
}
static Map<Integer,ListNode> nodeMap;
static Map<Long, Set<ListNode>> expireMap;
static PriorityQueue<Long> queue;
static int size;
static int capacity;
static ListNode head;
static ListNode tail;
public LRUWithExpire(int capacity){
nodeMap = new HashMap<>();
expireMap = new HashMap<>();
this.size = 0;
this.capacity = capacity;
queue = new PriorityQueue<>();
head = new ListNode();
tail = new ListNode();
head.next = tail;
tail.pre = head;
}
public int get(int key){
if(!nodeMap.containsKey(key)){
return -1;
}
ListNode node = nodeMap.get(key);
long now = System.currentTimeMillis();
if(node.expire<=now){
return -1;
}
moveToHead(node);
return node.value;
}
public void put(int key, int value, long expire){
removeByExpire();
if(nodeMap.containsKey(key)){
ListNode node = nodeMap.get(key);
moveToHead(node);
Set<ListNode> set = expireMap.get(node.expire);
set.remove(node);
node.expire = expire+System.currentTimeMillis();
if(!expireMap.containsKey(node.expire)){
set = new HashSet<>();
set.add(node);
queue.offer(node.expire);
expireMap.put(node.expire,set);
}
else{
set = expireMap.get(node.expire);
set.add(node);
}
return;
}
if(size>=capacity){
ListNode node = tail.pre;
removeNode(node);
nodeMap.remove(node.key);
Set<ListNode> set = expireMap.get(node.expire);
set.remove(node);
size--;
}
ListNode node = new ListNode(key,value,expire);
addToHead(node);
nodeMap.put(node.key,node);
if(!expireMap.containsKey(node.expire)){
Set<ListNode> set = new HashSet<>();
set.add(node);
expireMap.put(node.expire,set);
queue.offer(node.expire);
}
else{
Set<ListNode> set= expireMap.get(node.expire);
set.add(node);
}
}
public void removeByExpire(){
if(queue.isEmpty())
return;
long expire = queue.peek();
long now = System.currentTimeMillis();
if(expire<=now){
Set<ListNode> set = expireMap.get(expire);
for(ListNode n:set){
removeNode(n);
nodeMap.remove(n.key);
size--;
}
expireMap.remove(expire);
queue.poll();
}
}
public void addToHead(ListNode node){
node.next = head.next;
head.next = node;
node.next.pre = node;
node.pre = head;
}
public void removeNode(ListNode node){
node.pre.next = node.next;
node.next.pre = node.pre;
}
public void moveToHead(ListNode node){
removeNode(node);
addToHead(node);
}
}
测试代码
public static void main(String[] args) throws InterruptedException {
int v = 0;
LRUWithExpire lru = new LRUWithExpire(3);
lru.put(1,2,3000);
lru.put(2,3,3000);
lru.put(3,4,2000);
v = lru.get(3);
System.out.println(v);
Thread.sleep(2000);
lru.put(4,5,2000);
v = lru.get(1);
System.out.println(v);
v = lru.get(3);
System.out.println(v);
Thread.sleep(1000);
System.out.println(lru.get(1));
System.out.println(lru.get(2));
System.out.println(lru.get(4));
}
结果
4
2
-1
-1
-1
5