LRU算法为最近最久为使用,当空间满时,将最久未使用的数据释放。
插入与查询算作使用,被使用的数据放到表头,不怎么被使用的数据就被使用的数据移到表尾。
类似于FIFO算法,不同点在于,如果表内数据被使用,就将被使用数据移到表头。
双向链表可以方便的找到表头和表尾以及附近的结点。
HashMap可以通过key快速寻找所需数据。
import java.util.HashMap;
import java.util.Map;
public class LRU {
class DLinkedNode{
int key;
int value;
DLinkedNode prev;
DLinkedNode next;
public DLinkedNode(){}
public DLinkedNode(int key,int value){
this.key = key;
this.value = value;
}
}
//用于记录数据是否在表中
private Map<Integer,DLinkedNode> cache = new HashMap<>();
private int size;
private int capacity;
private DLinkedNode head,tail;
public LRU(int capacity){
this.size = 0;
this.capacity = capacity;
head = new DLinkedNode();
tail = new DLinkedNode();
head.next= tail;
tail.prev = head;
}
//从表中返回对应数据,并将数据移至表头
public int get(int key){
DLinkedNode node =cache.get(key);
if (node ==null){
return -1;
}
moveToHead(node);
return node.value;
}
//将数据加入表中,若表中已存在,则将数据移至表头;不存在则直接加到表头,size++
public void put(int key,int value){
DLinkedNode node = cache.get(key);
if (node==null){
DLinkedNode newNode = new DLinkedNode(key,value);
cache.put(key,newNode);
addToHead(newNode);
++size;
//判断大小是否超出,超出则去掉表尾
if (size>capacity){
DLinkedNode tail = removeTail();
cache.remove(tail.key);
--size;
}
}else {
node.value = value;
moveToHead(node);
}
}
private void addToHead(DLinkedNode node){
node.prev=head;
node.next=head.next;
head.next.prev=node;
head.next=node;
}
private void removeNode(DLinkedNode node){
node.prev.next=node.next;
node.next.prev=node.prev;
}
private void moveToHead(DLinkedNode node){
removeNode(node);
addToHead(node);
}
private DLinkedNode removeTail(){
DLinkedNode res = tail.prev;
removeNode(res);
return res;
}
}