LRU(Least Recently Used)是一种常见的缓存淘汰策略。它的核心思想是:当缓存空间不足时,优先淘汰最近最少使用的数据。 具体来说,LRU 策略会维护一个数据结构,用于记录每个数据的访问时间或使用次数。当需要淘汰数据时,LRU 策略会选择访问时间最早或使用次数最少的数据进行淘汰。 实现 LRU 策略的数据结构通常是哈希链表,它结合了哈希表和双向链表的优点。哈希表可以快速查找数据,双向链表可以方便地维护数据的访问顺序。 在实际应用中,LRU 策略常用于缓存系统,如数据库缓存、Web 浏览器缓存等。它可以提高缓存的命中率,减少数据的重复加载,从而提高系统的性能。 以下是使用 Java 实现 LRU 缓存的示例代码:
class LRUCache<K, V> {
private int capacity;
private Map<K, Node<K, V>> map;
private Node<K, V> head;
private Node<K, V> tail;
public LRUCache(int capacity) {
this.capacity = capacity;
this.map = new HashMap<>();
this.head = new Node<>();
this.tail = new Node<>();
this.head.next = this.tail;
this.tail.prev = this.head;
}
public V get(K key) {
Node<K, V> node = map.get(key);
if (node == null) {
return null;
}
removeNode(node);
addToHead(node);
return node.value;
}
public void put(K key, V value) {
Node<K, V> node = map.get(key);
if (node!= null) {
node.value = value;
removeNode(node);
addToHead(node);
return;
}
if (map.size() >= capacity) {
Node<K, V> removedNode = removeTail();
map.remove(removedNode.key);
}
Node<K, V> newNode = new Node<>(key, value);
map.put(key, newNode);
addToHead(newNode);
}
private void removeNode(Node<K, V> node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void addToHead(Node<K, V> node) {
node.next = head.next;
node.prev = head;
head.next.prev = node;
head.next = node;
}
private Node<K, V> removeTail() {
Node<K, V> removedNode = tail.prev;
removeNode(removedNode);
return removedNode;
}
private static class Node<K, V> {
K key;
V value;
Node<K, V> prev;
Node<K, V> next;
public Node(K key, V value) {
this.key = key;
this.value = value;
}
}
}
上述代码中,LRUCache类实现了 LRU 缓存。它使用一个哈希表map来存储键值对,同时使用一个双向链表来维护数据的访问顺序。head和tail分别表示链表的头节点和尾节点。 get方法用于获取缓存中指定键的值。如果键存在,则将对应节点移动到链表头部,并返回节点的值;否则返回null。 put方法用于向缓存中添加或更新键值对。如果键已存在,则更新节点的值,并将其移动到链表头部;否则创建新节点并添加到链表头部。如果缓存已满,则删除链表尾部的节点,并从哈希表中移除对应的键。 通过使用 LRU 策略,可以有效地管理缓存空间,提高缓存的命中率,从而提升系统的性能。具体的实现方式可以根据实际需求进行调整和优化。