《算法通关村——缓存机制了解LRU实现》

news2024/11/28 1:32:13

《算法通关村——缓存机制了解LRU实现》

介绍

LRU是"Least Recently Used"(最近最少使用)的缓存机制,它是一种常用的缓存算法,用于管理缓存中的数据项。LRU缓存机制的基本思想是,当缓存达到其容量限制时,会淘汰最久没有被访问的数据项,以为新的数据项腾出空间。

LRU缓存机制的实现方式通常是通过维护一个数据结构,例如链表或双向链表,来记录数据项的访问顺序。最近访问的数据项会被移到链表的头部(或双向链表的头部),而最久未被访问的数据项则位于链表的尾部。当需要从缓存中淘汰数据项时,就选择尾部的数据项进行淘汰,以确保淘汰最久未被访问的数据。

LRU缓存机制在实际应用中表现出良好的性能,因为它通常能够保留最常被访问的数据项,从而提高缓存命中率。然而,LRU的实现可能需要一定的额外开销,因为需要维护访问顺序的数据结构,而且在某些情况下,可能需要频繁地移动数据项,这可能会导致性能问题。因此,在特定情况下,可以考虑其他缓存淘汰算法,如LFU(Least Frequently Used)或FIFO(First-In, First-Out)等。

当涉及到缓存淘汰算法时,除了LRU,还有其他一些常见的算法,其中包括LFU(Least Frequently Used)和FIFO(First-In, First-Out):

  1. LFU(Least Frequently Used):

    • LFU算法基于数据项被访问的频率来进行缓存淘汰决策。它认为访问频率较低的数据项应该被淘汰,因为它们被认为是不太重要或不太常用的数据。
    • LFU算法通常使用一个计数器来跟踪每个数据项被访问的次数。当需要淘汰数据项时,选择具有最低访问次数的数据项进行淘汰。
    • 一些变种的LFU算法也考虑了时间因素,以便更好地适应数据访问模式的变化。这些变种可能会在计数器的基础上引入时间衰减因素。
  2. FIFO(First-In, First-Out):

    • FIFO算法是一种非常简单的缓存淘汰策略。它按照数据项最早进入缓存的顺序来进行淘汰。也就是说,首先进入缓存的数据项最先被淘汰,而最后进入的数据项最后被淘汰。
    • FIFO算法通常使用一个队列来维护数据项的顺序。当需要淘汰数据项时,从队列的头部移除最早进入的数据项。
    • FIFO算法的主要优点是其简单性,但它可能不太适用于某些访问模式,因为它不考虑数据项的访问频率或重要性,只根据进入顺序进行淘汰。

选择何种缓存淘汰算法通常取决于具体的应用场景和需求。不同的算法有不同的优缺点,因此需要根据数据访问模式、性能需求以及实际应用的特点来选择最合适的算法。在某些情况下,也可以考虑结合多个算法或自定义淘汰策略以满足特定的需求。

代码实现

package AlgorithmFifth;

import java.util.HashMap;
import java.util.Map;

public class LRUCache {
    class DLinkedNode {
        int key;
        int value;
        DLinkedNode prev;
        DLinkedNode next;

        public DLinkedNode() {
        }

        public DLinkedNode(int _key,int _value){
            key = _key;
            value = _value;
        }
    }
    private Map<Integer,DLinkedNode> cache = new HashMap<>();
    private int size;
    private int capacity;
    private DLinkedNode head,tail;

    public LRUCache(int capacity){
        this.size = 0;
        this.capacity = capacity;
        // 使用伪头部和伪尾部节点
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head.next = tail;
        tail.prev = head;
    }

    public int get(int key){
        DLinkedNode node = cache.get(key);
        if(node == null){
            return -1;
        }
        // 如果key存在,先通过哈希表定位,再移到头部
        moveToHead(node);
        return node.value;
    }

    public void put(int key,int value){
        DLinkedNode node = cache.get(key);
        if(node == null){
            // 如果key不存在创建一个新节点
            DLinkedNode newNode = new DLinkedNode(key,value);
            // 添加进哈希表
            cache.put(key,newNode);
            // 添加至双向链表的头部
            addToHead(newNode);
            ++size;
            if(size > capacity){
                // 如果超出容量,删除双向链表的尾部节点
                DLinkedNode tail = removeTail();
                // 删除哈希表中对应的项
                cache.remove(tail.key);
                size--;
            }
        }else {
            // 如果key存在,先通过哈希表定位,在修改value,并移到头部
            node.value = value;
            moveToHead(node);
        }
    }
    private void addToHead(DLinkedNode node) {
        node.prev = head;
        node.next = head.next;
        head.next.prev = node;
        head.next = node;
    }

    private void removeNode(DLinkedNode node){
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }

    private void moveToHead(DLinkedNode node){
        removeNode(node);
        addToHead(node);
    }

    private DLinkedNode removeTail(){
        DLinkedNode res = tail.prev;
        removeNode(res);
        return res;
    }

    public static void main(String[] args) {
        LRUCache lruCache = new LRUCache(2);
        lruCache.put(1,1);
        lruCache.put(2,2);
        System.out.println(lruCache.get(1));
        lruCache.put(3,3);
        System.out.println(lruCache.get(2));
        lruCache.put(4,4);
        System.out.println(lruCache.get(1));
        System.out.println(lruCache.get(3));
        System.out.println(lruCache.get(4));
    }
}

近期在自学 Java 做项目,加入了一个编程学习圈子,里面有编程学习路线和原创的项目教程,感觉非常不错。还可以 1 对 1 和大厂嘉宾交流答疑,也希望能对大家有帮助,扫 ⬇️ 二维码即可加入。

在这里插入图片描述

也可以点击链接:我正在「编程导航」和朋友们讨论有趣的话题,你⼀起来吧?

也可以加我QQ(2837468248)咨询说明来意!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1160380.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT对未来发展的影响?一般什么时候用到GPT

ChatGPT以其强大的自然语言处理能力对未来的发展具有重要影响。以下是ChatGPT的潜在影响和一般使用情况&#xff1a; 改善自然语言理解和生成&#xff1a;ChatGPT和类似的模型可以改善机器对人类语言的理解和生成。这将有助于改进各种应用领域&#xff0c;包括智能助手、聊天机…

功放电路有这么多种,哪种音质最好呀?

功放电路种类很多&#xff0c;首先得知道各个功放电路的特点。 第一种&#xff0c;A类功放&#xff08;甲类功放&#xff09;&#xff0c;在信号的整个周期内都不会出现电流截止(即停止输出)的一类放大器。 但是A类放大器工作时会产生高热&#xff0c;效率很低&#xff0c;优…

使用postman进行接口自动化测试

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

数据结构之栈的实现

&#x1d649;&#x1d65e;&#x1d658;&#x1d65a;!!&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦ &#x1f44f;&#x1f3fb;‧✧̣̥̇: Solitary-walk ⸝⋆ ━━━┓ - 个性标签 - &#xff1a;来于“云”的“羽球人”…

干货分享,大厂内部压测方案设计!

01、为什么要做压测 1、什么是压力测试&#xff1f; 不断向被测对象施加压力&#xff0c;测试系统在压力情况下的表现。 2、压力测试的目的是什么&#xff1f; 测试得出系统的极限性能指标&#xff0c;从而给出合理的承诺值或者容量告警&#xff1b; 找出系统的性能瓶颈&a…

5.1 实体完整性

思维导图&#xff1a; 前言 第5章 数据库完整性笔记 定义&#xff1a; 完整性&#xff1a;确保数据的正确性和相容性。 正确性&#xff1a;数据与现实世界语义相符、反映实际状况。相容性&#xff1a;同一对象在数据库的不同关系表中数据逻辑上是一致的。 示例&#xff1a; 学…

【发表案例】2区正刊,网络安全、智能系统领域,2个月3天录用,11天见刊,16天检索!

计算机类SCIE 【期刊简介】IF&#xff1a;4.0-5.0&#xff0c;JCR2区&#xff0c;中科院3区 【检索情况】SCIE 在检&#xff0c;正刊 【征稿领域】提高安全性和隐私性的边缘/云的智能方法的研究&#xff0c;如数字孪生等 【截稿日期】2023.11.30 录用案例&#xff1a;2个月…

LCD驱动程序——Framebuffer应用编程

1.LCD 操作原理 在 Linux 系统中通过 Framebuffer 驱动程序来控制 LCD。Frame 是帧的意思&#xff0c;buffer 是缓冲的意思&#xff0c;这意味着 Framebuffer 就是一块内存&#xff0c;里面保存着一帧图像。Framebuffer 中保存着一帧图像的每一个像素颜色值&#xff0c;假设 L…

怎样利用 AI 大模型,辅助研发管理与效能提升?

AI 大模型已经逐渐渗透到各行各业的应用场景中&#xff0c;在软件研发领域也不例外。在软件研发领域&#xff0c;从需求分析到软件设计&#xff0c;从软件开发到测试&#xff0c;以及最后发布上线&#xff0c;AI 在各个环节都发挥着重要作用。10 月 21 日&#xff0c;思码逸首席…

react条件渲染

目录 前言 1. 使用if语句 2. 使用三元表达式 3. 使用逻辑与操作符 列表渲染 最佳实践和注意事项 1. 使用合适的条件判断 2. 提取重复的逻辑 3. 使用适当的key属性 总结 前言 在React中&#xff0c;条件渲染指的是根据某个条件来决定是否渲染特定的组件或元素。这在构…

图解刘润2023年度演讲--进化的力量思维导图精华

大家好&#xff0c;我是老原。 周末&#xff0c;商业顾问刘润发表了年度演讲&#xff1a;《进化的力量&#xff1a;寒武纪大爆发》。 这两天出差期间&#xff0c;陆陆续续看完了这个长达4小时的演讲&#xff0c;梳理了2023年到底发生了些什么&#xff0c;现在的环境如何…… …

技术阅读周刊第三期

技术阅读周刊&#xff0c;每周更新。 历史更新 20231013&#xff1a;第一期20231022&#xff1a;第二期 Understanding The Linux TTY Subsystem URL: https://ishuah.com/2021/02/04/understanding-the-linux-tty-subsystem/本文讲解了 Linux TTY 的历史故事和来源。 TTY 是 t…

HNU-算法设计与分析-讨论课1

第一次小班讨论 &#xff08;以组为单位&#xff0c;每组一题&#xff0c;每组人人参与、合理分工&#xff0c;ppt中标记分工&#xff0c;尽量都有代码演示&#xff09; 1.算法分析题 2-10、2-15(要求&#xff1a;有ppt&#xff08;可代码演示&#xff09;) 2.算法实现题 2-4、…

蓝桥杯(C++ 扫雷)

题目&#xff1a; 思想&#xff1a; 1、遍历每个点是否有地雷&#xff0c;有地雷则直接返回为9&#xff0c;无地雷则遍历该点的周围八个点&#xff0c;计数一共有多少个地雷&#xff0c;则返回该数。 代码&#xff1a; #include<iostream> using namespace std; int g[…

【Java 进阶篇】Java中的响应输出字节数据

在Java Web应用程序开发中&#xff0c;处理响应是一个常见的任务。有时&#xff0c;您可能需要向客户端发送字节数据&#xff0c;而不仅仅是文本或HTML内容。这可以用于传输各种内容&#xff0c;如图像、文件、视频等。本文将详细介绍如何在Java中使用Response对象输出字节数据…

sql语句性能进阶必须了解的知识点——索引失效分析

在前面的文章中讲解了sql语句的优化策略 sql语句性能进阶必须了解的知识点——sql语句的优化方案-CSDN博客 sql语句的优化重点还有一处&#xff0c;那就是—— 索引&#xff01;好多sql语句慢的本质原因就是设置的索引失效或者根本没有建立索引&#xff01;今天我们就来总结一…

160. 相交链表、Leetcode的Python实现

博客主页&#xff1a;&#x1f3c6;看看是李XX还是李歘歘 &#x1f3c6; &#x1f33a;每天分享一些包括但不限于计算机基础、算法等相关的知识点&#x1f33a; &#x1f497;点关注不迷路&#xff0c;总有一些&#x1f4d6;知识点&#x1f4d6;是你想要的&#x1f497; ⛽️今…

从零开始制作一个桶装水小程序

随着互联网的发展&#xff0c;越来越多的消费者通过线上购买桶装水。为了满足这一需求&#xff0c;我们需要制作一个专门的小程序商城&#xff0c;以便用户可以方便地购买桶装水。本文将通过乔拓云平台&#xff0c;从零开始制作一个桶装水小程序&#xff0c;并详细解析制作步骤…

二、类与对象(一)

1 面向过程和面向对象初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。以洗衣服为例&#xff0c;通常洗衣服会经历以下过程&#xff1a; 而C是基于面向对象的&#xff0c;关注的是对象&#xff0c…

云安全—K8s APi Server 6443 攻击面

0x00 前言 在未授权的一文中&#xff0c;详细描述了k8s api中的8080端口未授权的问题&#xff0c;那么本篇主要来说6443端口的利用。 0x01 API连接攻击面 1.匿名用户访问 匿名开放方式&#xff1a;kubectl create clusterrolebinding cluster-system-anonymous --clusterro…