LRU 缓存机制 —— 你的 Java 代码过关了吗?
2023-12-23 04:35:22
-
`
-
`
LRU 缓存是什么?
最近最少使用 (LRU) 缓存是一种用于存储数据的缓存机制。它遵循这样一个原则:当缓存已满时,最近最少使用的项目将被移除,为新项目腾出空间。这使得 LRU 缓存非常适合存储经常访问的数据,因为它们更有可能在不久的将来再次被访问。
在 LeetCode 中,146. LRU 缓存是经典问题之一。它要求你实现一个 LRUCache 类,提供以下方法:
class LRUCache {
int capacity;
HashMap<Integer, Node> map = new HashMap<>();
Node head = new Node(0, 0);
Node tail = new Node(0, 0);
public LRUCache(int capacity) {
this.capacity = capacity;
head.next = tail;
tail.prev = head;
}
public int get(int key) {
if (map.containsKey(key)) {
Node node = map.get(key);
removeNode(node);
addNode(node);
return node.value;
}
return -1;
}
public void put(int key, int value) {
if (map.containsKey(key)) {
Node node = map.get(key);
removeNode(node);
node.value = value;
addNode(node);
} else {
Node node = new Node(key, value);
map.put(key, node);
addNode(node);
if (map.size() > capacity) {
map.remove(tail.prev.key);
removeNode(tail.prev);
}
}
}
private void removeNode(Node node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void addNode(Node node) {
node.next = head.next;
head.next = node;
node.next.prev = node;
node.prev = head;
}
class Node {
int key;
int value;
Node prev;
Node next;
public Node(int key, int value) {
this.key = key;
this.value = value;
}
}
}
实现 LRU 缓存的思路
在 Java 中实现 LRU 缓存,首先需要一个数据结构来存储缓存项。这里使用了一个双向链表,链表中的节点表示缓存项,每个节点包含一个键和一个值。双向链表允许我们轻松地插入和删除节点,这对于 LRU 缓存非常重要。
为了实现 LRU 缓存的功能,我们需要维护一个哈希表,哈希表的键是缓存项的键,哈希表的值是缓存项在双向链表中的节点。这允许我们快速地查找缓存项并更新其位置。
当我们向缓存中添加一个新的项时,如果缓存已满,我们需要删除最不常用的项。我们使用双向链表来实现这一点。当我们添加一个新的项时,我们将它添加到链表的头部。当缓存已满时,我们将链表尾部的项删除。
当我们从缓存中获取一个项时,如果该项存在,我们将它从链表中删除并将其添加到链表的头部。这确保了该项在链表中的位置总是最新的。
复杂度分析
LRUCache 的时间复杂度主要取决于底层数据结构的实现。在我们的实现中,我们使用了一个双向链表和一个哈希表。
查找和更新操作的时间复杂度为 O(1),因为我们可以直接通过哈希表找到对应的节点。
添加和删除操作的时间复杂度为 O(1),因为我们只需要修改链表的头部或尾部即可。
总结
LRU 缓存是一种非常重要的计算机算法,它广泛应用于各种系统中。在本文中,我们提供了 LRU 缓存的详细 Java 实现,结合代码分析和示例,帮助你理解和掌握该算法。