# 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;
        }
    }
相关推荐
玖玥拾3 小时前
LeetCode 392 判断子序列
笔记·算法·leetcode
weixin_399380693 小时前
TongWeb7.0.4.9M11一键安装脚本(by sy)
java·spring
CallFay云起未来3 小时前
AI客服能不能减少人工回复?从重复咨询到人机协同的落地分析
java·大数据·人工智能·文心一言
我命由我123453 小时前
Android 开发 - 获取当前设备屏幕的旋转角度
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
Elastic 中国社区官方博客4 小时前
OpenTelemetry Java 扩展:无需分叉 agent 即可自定义追踪
java·大数据·运维·开发语言·数据库·人工智能·elasticsearch
京东云开发者4 小时前
上游给空、下游拿到 -1,我把故障一直追到了 commons-beanutils 的构造函数
java·ai编程
阿无,4 小时前
Java多线程面试题之AQS
java·开发语言
数据狐(Datafox)4 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
摇滚侠4 小时前
《SpringBoot 3:入门与应用实战》第 7 章 AOP 思想与实现 阅读笔记 15
java·spring boot·笔记
01传说4 小时前
redis开机自启脚本
数据库·redis·缓存