# Java手写LRU缓存算法

Java手写LRU缓存算法

1. 算法思维导图

LRU缓存算法 实现原理 手写必要性 市场调查 实现介绍 详细步骤 步骤1 步骤2 步骤3 代码实现 函数1 函数2 函数3 总结与思维拓展 完整代码 代码行注释

2. 实现原理

LRU(Least Recently Used)缓存算法是一种常用的缓存淘汰策略,它的基本思想是根据数据的访问时间来进行淘汰,最近使用的数据被认为是将来也可能会被使用的,因此被保留,而较久未使用的数据被认为是将来可能不会再使用的,因此被淘汰。

3. 手写必要性

手写LRU缓存算法的必要性在于深入理解算法的实现原理和核心思想,同时可以根据实际需求进行优化和定制化,提高缓存的效率和命中率。

4. 市场调查

根据市场调查,LRU缓存算法在各个领域都有广泛的应用,特别适用于需要频繁读取和更新数据的场景,如数据库查询、网络请求、页面缓存等。同时,随着大数据和云计算的发展,对高效缓存算法的需求也越来越大。

5. 实现介绍

5.1 详细步骤

  1. 初始化缓存大小和哈希表
  2. 定义双向链表节点类
  3. 定义LRU缓存类,包括构造函数和核心方法
  4. 实现核心方法:
    1. 查询缓存:根据键值在哈希表中查找对应的节点,若存在则将节点移动到链表头部,并返回值;若不存在则返回-1。
    2. 更新缓存:根据键值在哈希表中查找对应的节点,若存在则更新节点值并将节点移动到链表头部;若不存在则创建新节点并将节点插入链表头部,同时在哈希表中添加新节点。
    3. 插入缓存:根据键值在哈希表中查找对应的节点,若存在则更新节点值并将节点移动到链表头部;若不存在则创建新节点并将节点插入链表头部,同时在哈希表中添加新节点。若缓存已满,则删除链表尾部节点,并在哈希表中删除对应的节点。
    4. 删除缓存:根据键值在哈希表中查找对应的节点,若存在则删除节点,并在哈希表中删除对应的节点。

5.2 代码实现

java 复制代码
// 双向链表节点类
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. 完整代码

java 复制代码
// 双向链表节点类
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;
        }
    }
相关推荐
我命由我1234512 分钟前
Android 开发问题:为 PDFView 设置一个带有黑色边框的背景 drawable,但边框没有生效
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
拳里剑气1 小时前
C++算法:BFS解决FloodFill算法
c++·算法·bfs·宽度优先
都叫我大帅哥2 小时前
从Python到Java:为什么企业级Agent最终会选择Java?
java·ai编程
wanderist.3 小时前
Lambda表达式在算法竞赛中的应用
java·开发语言·算法
稚南城才子,乌衣巷风流3 小时前
支配树(Dominator Tree)详解:概念、算法与应用
算法
稚南城才子,乌衣巷风流4 小时前
动态开点:原理、实现与应用场景
数据结构·算法
yyds_yyd_100864 小时前
1464. 数组中两元素的最大乘积(2026.07.27)
数据结构·c++·算法·leetcode
腻害兔4 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:IM 即时通讯模块,一个被低估的「全功能聊天系统」
java·前端·vue.js·产品经理·ai编程
Alan_6914 小时前
商品详情优化三板斧-拆分-多级缓存-GC调参
后端·缓存