什么是LRU算法?
LRU:Least Recently Used的缩写,即最近最少使用。LRU算法是内存淘汰场景下使用的一个算法,当内存满了,不得已删除某些数据时,然后选择最久时间没使用的数据进行删除。
实现方式:
实现LRU算法可以通过HashMap+双向链表的方式来实现,整个过程都是O(1)的时间复杂度,效率很高。
代码:
public class LRUCache {
//定义双向链表节点类
class DLinkNode{
int key;
int value;
DLinkNode prev;
DLinkNode next;
public DLinkNode(){
}
public DLinkNode(int key,int value){
this.key=key;
this.value=value;
}
}
private Map<Integer,DLinkNode> cacheMap = new HashMap<Integer,DLinkNode>();
private int size;
private int capacity;
private DLinkNode head, tail;
public LRUCache(int capacity) {
this.size = 0;
this.capacity=capacity;
//使用伪头部和伪尾部节点
head=new DLinkNode();
tail=new DLinkNode();
head.next=tail;
tail.prev=head;
}
public int get(int key){
DLinkNode node = cacheMap.get(key);
if (node==null){
return -1;
}
moveToHead(node);
return node.value;
}
public void put(int key,int value){
DLinkNode node = cacheMap.get(key);
if (node==null){
DLinkNode newNode = new DLinkNode(key,value);
cacheMap.put(key,newNode);
addToHead(newNode);
size++;
if (size>capacity){
DLinkNode taliNode = removeTail();
cacheMap.remove(taliNode.key);
size--;
}
}else {
node.value=value;
moveToHead(node);
}
}
public void moveToHead(DLinkNode node){
//删除原节点
removeNode(node);
//连接到头部
addToHead(node);
}
public void removeNode(DLinkNode node){
node.prev.next=node.next;
node.next.prev=node.prev;
}
public void addToHead(DLinkNode node){
node.prev=head;
node.next=head.next;
head.next.prev=node;
head.next=node;
}
public DLinkNode removeTail(){
DLinkNode res = tail.prev;
removeNode(res);
return res;
}
}
代码测试:
public static void main(String[] args) {
//定义容量大小为2
LRUCache lruCache = new LRUCache(2);
lruCache.put(1,1);//现在存储的顺序为{1=1}
lruCache.put(2,2);//现在存储的顺序为{2=2,1=1}
System.out.println(lruCache.get(1));//现在存储的顺序为{1=1,2=2}
lruCache.put(3,3);//现在存储的顺序为{3=3,1=1}
System.out.println(lruCache.get(2));//2已经不存在,返回-1
lruCache.put(4,4);//现在存储的顺序为{4=4,3=3}
System.out.println(lruCache.get(1));//1已经不存在,返回-1
System.out.println(lruCache.get(3));
System.out.println(lruCache.get(4));
}