# 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;
        }
    }
相关推荐
灰灰老师20 分钟前
数据分析系列--[11] RapidMiner,K-Means聚类分析(含数据集)
人工智能·算法·机器学习·数据挖掘·数据分析·kmeans·rapidminer
追求源于热爱!1 小时前
记4(可训练对象+自动求导机制+波士顿房价回归预测
图像处理·人工智能·算法·机器学习·回归
taopi20241 小时前
android java系统弹窗的基础模板
android·java·开发语言
如风暖阳1 小时前
Redis背景介绍
数据库·redis·缓存
松仔log1 小时前
Java多线程——对象的组合
java·开发语言·jvm
qq_433618441 小时前
哈夫曼树
数据结构·算法
余辉zmh2 小时前
【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(二)
c++·算法·leetcode·贪心算法
酷爱码2 小时前
springboot 动态配置定时任务
java·spring boot·后端
余辉zmh2 小时前
【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(一)
c++·算法·leetcode·贪心算法
taoyong0012 小时前
代码随想录算法训练营第三十七天-动态规划-完全背包-377. 组合总和 Ⅳ
c++·算法·leetcode·动态规划