LRU:least recently used 最近最少使用的
LRU的算法核心是哈希链表(本质就是HashMap+DoubleLinkedList)
编码实现:
public class LRUDemo<K, V> {
private int cacheSize;
private Map<K, Node<K, V>> map;
private DoubleLinkList<K, V> linkList;
public LRUDemo(int cacheSize) {
this.cacheSize = cacheSize;
map = new HashMap<>();
linkList = new DoubleLinkList<>();
}
public V get(K key) {
if (!map.containsKey(key)) {
return null;
}
Node<K, V> node = map.get(key);
linkList.removeNode(node);
linkList.addHead(node);
return node.value;
}
public void put(K key, V value) {
if (map.containsKey(key)) {
Node<K, V> node = map.get(key);
node.value = value;
linkList.removeNode(node);
linkList.addHead(node);
} else {
if (map.size() >= cacheSize) {
linkList.removeNode(linkList.getLastNode());
}
Node<K, V> newNode = new Node<>(key, value);
linkList.addHead(newNode);
map.put(key, newNode);
}
}
class Node<K, V> {
K key;
V value;
Node<K, V> prev;
Node<K, V> next;
Node() {
prev = next = null;
}
Node(K key, V value) {
this.key = key;
this.value = value;
prev = next = null;
}
@Override
public String toString() {
return "Node{" +
"key=" + key +
", value=" + value +
'}';
}
}
class DoubleLinkList<K, V> {
Node<K, V> head;
Node<K, V> tail;
DoubleLinkList() {
head = new Node<>();
tail = new Node<>();
head.next = tail;
tail.prev = head;
}
public void addHead(Node<K, V> node) {
node.prev = head;
node.next = head.next;
head.next.prev = node;
head.next = node;
}
public void removeNode(Node<K, V> node) {
if (node != null && node != head && node != tail) {
node.prev.next = node.next;
node.next.prev = node.prev;
node.prev = null;
node.next = null;
}
}
public Node<K, V> getLastNode() {
return tail.prev != head ? tail.prev : null;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
Node<K, V> node = head.next;
while (node != null && node != tail) {
sb.append(node.key);
node = node.next;
if (node != tail) {
sb.append(",");
}
}
return sb.append("]").toString();
}
}
public static void main(String[] args) {
LRUDemo<Integer, Integer> lruDemo = new LRUDemo<>(3);
lruDemo.put(1, 1);
lruDemo.put(2, 2);
lruDemo.put(3, 3);
System.out.println(lruDemo.linkList);
lruDemo.put(4, 4);
System.out.println(lruDemo.linkList);
lruDemo.put(3, 3);
System.out.println(lruDemo.linkList);
lruDemo.put(3, 33);
System.out.println(lruDemo.linkList);
lruDemo.put(3, 3);
System.out.println(lruDemo.linkList);
lruDemo.put(5, 5);
System.out.println(lruDemo.linkList);
lruDemo.get(4);
System.out.println(lruDemo.linkList);
}
}
运行结果:
[3,2,1]
[4,3,2]
[3,4,2]
[3,4,2]
[3,4,2]
[5,3,4]
[4,5,3]