LRU是什么?
LRU(Least Recently Use)是一种缓存清楚策略。最近最少使用的被清除。
如何实现?
HashMap + DobleLinkedList(双向链表),这样做的好处是可以做到O(1)的时间复杂度对缓存进行,删除和更新。
主要有两个操作:(具体的处理细节,代码有注释!)
- 获取缓存
- 缓存不存在 返回-1
- 存在
- 增加缓存存在如下情况:
- 缓存存在
- 相同key value相同
- 相同key value不相同
- 缓存不存在
- 缓存已满
- 缓存未满
- 缓存存在
代码采用哨兵模式,简化了繁琐的判断head和tail的操作。(空间换时间的思路)。
Talk is cheap!Just show the code!
对应leetcode LRU Cache
代码执行效率如下:
import java.util.HashMap;
import java.util.Map;
/**
* @author: zy
* @Date: 2020-02-07 09:12
* @Copyright: 2019 www.lenovo.com Inc. All rights reserved.
* leetcode LRUCache can use as testcase.
*/
public class LRUCache {
/**
* LinkedListHash Map
*/
private Map<Integer, DoubleLinkedList> cache = new HashMap<>(16);
/**
* cache total size
*/
private int capacity;
/**
* cache current size
*/
private int size;
/**
* use solider design to make code sample,less if.
*/
private DoubleLinkedList head;
private DoubleLinkedList tail;
public LRUCache(int capacity) {
if (capacity == 0) {
throw new RuntimeException("capacity can not be zero!!!");
}
head = new DoubleLinkedList(0, 0);
tail = new DoubleLinkedList(0, 0);
head.next = tail;
tail.pre = head;
this.capacity = capacity;
}
/**
* Doubly linked list
*/
static class DoubleLinkedList {
private int value;
private int key;
DoubleLinkedList pre = null;
DoubleLinkedList next = null;
DoubleLinkedList(int key, int value) {
this.value = value;
this.key = key;
}
}
/**
* get cache
* two situations:
* a:
* cache exist
* delete old node.
* insert node to head.
* b.cache not exist
* return -1
*
* @param key
* @return
*/
public int get(int key) {
DoubleLinkedList node = cache.get(key);
if (node == null) {
return -1;
}
deleteNode(node);
insertToHead(key, node);
return node.value;
}
/**
* put cache
* two situations
* a.cache exist
* 1.same key has same value.
* 2.same key has diff value.
* b.cache not exist
* 1.cache full
* 2.cache not full
*
* @param key
* @param value
*/
public void put(int key, int value) {
DoubleLinkedList node = cache.get(key);
DoubleLinkedList newNode = new DoubleLinkedList(key, value);
if (node == null) {
insertToHead(key, newNode);
} else {
deleteNode(node);
insertToHead(key, newNode);
}
cache.put(key, newNode);
}
private void insertToHead(int key, DoubleLinkedList node) {
if (size >= capacity) {
cache.remove(tail.pre.key);
deleteNode(tail.pre);
}
node.next = head.next;
head.next.pre = node;
head.next = node;
node.pre = head;
size++;
}
private void deleteNode(DoubleLinkedList node) {
node.pre.next = node.next;
node.next.pre = node.pre;
size--;
}
}
复制代码