Java手写LRU缓存算法
1. 算法思维导图
2. 实现原理
LRU(Least Recently Used)缓存算法是一种常用的缓存淘汰策略,它的基本思想是根据数据的访问时间来进行淘汰,最近使用的数据被认为是将来也可能会被使用的,因此被保留,而较久未使用的数据被认为是将来可能不会再使用的,因此被淘汰。
3. 手写必要性
手写LRU缓存算法的必要性在于深入理解算法的实现原理和核心思想,同时可以根据实际需求进行优化和定制化,提高缓存的效率和命中率。
4. 市场调查
根据市场调查,LRU缓存算法在各个领域都有广泛的应用,特别适用于需要频繁读取和更新数据的场景,如数据库查询、网络请求、页面缓存等。同时,随着大数据和云计算的发展,对高效缓存算法的需求也越来越大。
5. 实现介绍
5.1 详细步骤
- 初始化缓存大小和哈希表
- 定义双向链表节点类
- 定义LRU缓存类,包括构造函数和核心方法
- 实现核心方法:
- 查询缓存:根据键值在哈希表中查找对应的节点,若存在则将节点移动到链表头部,并返回值;若不存在则返回-1。
- 更新缓存:根据键值在哈希表中查找对应的节点,若存在则更新节点值并将节点移动到链表头部;若不存在则创建新节点并将节点插入链表头部,同时在哈希表中添加新节点。
- 插入缓存:根据键值在哈希表中查找对应的节点,若存在则更新节点值并将节点移动到链表头部;若不存在则创建新节点并将节点插入链表头部,同时在哈希表中添加新节点。若缓存已满,则删除链表尾部节点,并在哈希表中删除对应的节点。
- 删除缓存:根据键值在哈希表中查找对应的节点,若存在则删除节点,并在哈希表中删除对应的节点。
5.2 代码实现
// 双向链表节点类
class Node {int key;int value;Node prev;Node next;public Node(int key, int value) {this.key = key;this.value = value;}
}// LRU缓存类
class LRUCache {private int capacity;private Map<Integer, Node> cache;private Node head;private Node tail;public LRUCache(int capacity) {this.capacity = capacity;this.cache = new HashMap<>();this.head = new Node(0, 0);this.tail = new Node(0, 0);this.head.next = this.tail;this.tail.prev = this.head;}public int get(int key) {if (cache.containsKey(key)) {Node node = cache.get(key);moveToHead(node);return node.value;}return -1;}public void put(int key, int value) {if (cache.containsKey(key)) {Node node = cache.get(key);node.value = value;moveToHead(node);} else {Node newNode = new Node(key, value);cache.put(key, newNode);addToHead(newNode);if (cache.size() > capacity) {Node tailNode = removeTail();cache.remove(tailNode.key);}}}private void moveToHead(Node node) {removeNode(node);addToHead(node);}private void addToHead(Node node) {node.prev = head;node.next = head.next;head.next.prev = node;head.next = node;}private void removeNode(Node node) {node.prev.next = node.next;node.next.prev = node.prev;}private Node removeTail() {Node tailNode = tail.prev;removeNode(tailNode);return tailNode;}
}
6. 总结与思维拓展
通过手写LRU缓存算法,我们深入理解了其实现原理和核心思想。LRU缓存算法可以提高缓存的效率和命中率,适用于各种需要频繁读取和更新数据的场景。在实际应用中,我们可以根据具体需求进行优化和定制化,进一步提升算法的性能。
7. 完整代码
// 双向链表节点类
class Node {int key;int value;Node prev;Node next;public Node(int key, int value) {this.key = key;this.value = value;}
}// LRU缓存类
class LRUCache {private int capacity;private Map<Integer, Node> cache;private Node head;private Node tail;public LRUCache(int capacity) {this.capacity = capacity;this.cache = new HashMap<>();this.head = new Node(0, 0);this.tail = new Node(0, 0);this.head.next = this.tail;this.tail.prev = this.head;}public int get(int key) {if (cache.containsKey(key)) {Node node = cache.get(key);moveToHead(node);return node.value;}return -1;}public void put(int key, int value){if (cache.containsKey(key)) {Node node = cache.get(key);node.value = value;moveToHead(node);} else {Node newNode = new Node(key, value);cache.put(key, newNode);addToHead(newNode);if (cache.size() > capacity) {Node tailNode = removeTail();cache.remove(tailNode.key);}}}private void moveToHead(Node node) {removeNode(node);addToHead(node);}private void addToHead(Node node) {node.prev = head;node.next = head.next;head.next.prev = node;head.next = node;}private void removeNode(Node node) {node.prev.next = node.next;node.next.prev = node.prev;}private Node removeTail() {Node tailNode = tail.prev;removeNode(tailNode);return tailNode;}}