算法介绍:
最近最久未使用(Least Recently Used LRU)算法是⼀种缓存淘汰策略。该算法的思路是,将最近一段时间内最久未使用的页面置换出去。 升级版LRUK算法见
基于LRU-K算法设计本地缓存实现流量削峰https://blog.csdn.net/love254443233/article/details/82598381?spm=1001.2014.3001.5502
import java.util.HashMap;
import java.util.Map;
/**
* Design a data structure that follows the constraints of a Least Recently Used (LRU) cache.
* <p>
* Implement the LRUCache class:
* <p>
* LRUCache(int capacity) Initialize the LRU cache with positive size capacity.
* int get(int key) Return the value of the key if the key exists, otherwise return -1.
* void put(int key, int value) Update the value of the key if the key exists. Otherwise, add the key-value pair to the cache. If the number of keys exceeds the capacity from this operation, evict the least recently used key.
* The functions get and put must each run in O(1) average time complexity.
*/
public class LRUCache {
static class Node {
Node prev;
Node next;
int key;
int value;
public Node() {
}
public Node(int key, int value) {
this.key = key;
this.value = value;
}
}
Map<Integer, Node> cachMap = new HashMap<>(16);
Node head;
Node end;
int size;
int capacity;
public LRUCache(int capacity) {
this.size = 0;
this.capacity = capacity;
head = new Node();
end = new Node();
head.next = end;
end.prev = head;
}
public int get(int key) {
Node node = cachMap.get(key);
if (node == null) {
return -1;
}
// 移动到链表头
moveToHead(node, head);
return node.value;
}
public void put(int key, int value) {
Node node = cachMap.get(key);
if (node == null) {
Node data = new Node(key, value);
cachMap.put(key, data);
addToHead(data, head);
++size;
if (size > capacity) {
cachMap.remove(end.prev.key);
delete(end.prev);
--size;
}
return;
}
node.value = value;
moveToHead(node, head);
}
/**
* 添加到链表头
*
* @param node 数据节点
* @param head 头节点
*/
private static void addToHead(Node node, Node head) {
node.next = head.next;
node.prev = head;
head.next = node;
node.next.prev = node;
}
/**
* 移除当前节点
*
* @param data 数据节点
*/
private static void delete(Node data) {
if (data.prev != null) {
Node prev = data.prev;
prev.next = data.next;
data.next.prev = prev;
}
}
/**
* 把节点移动到链表头
*
* @param node 节点
* @param head 头节点
*/
private static void moveToHead(Node node, Node head) {
// 移除node
delete(node);
// 把node添加到链表头
addToHead(node, head);
}
}
单元测试
import junit.framework.TestCase;
import org.junit.Assert;
public class LRUCacheTest extends TestCase {
public void testGet() {
LRUCache lruCache = new LRUCache(2);
// node 为空,结果为-1
Assert.assertEquals(-1, lruCache.get(1));
// node存在
lruCache.put(1, 2);
Assert.assertEquals(2, lruCache.get(1));
// node存在,重复put
lruCache.put(1, 3);
Assert.assertEquals(3, lruCache.get(1));
// cache数量超过容器数量,会移除链表尾节点
lruCache.put(2, 3);
lruCache.put(3, 4);
Assert.assertEquals(-1, lruCache.get(1));
}
}