【揭秘】如何使用LinkedHashMap来实现一个LUR缓存?

news2024/11/27 5:27:51

【揭秘】如何使用LinkedHashMap来实现一个LUR缓存? - 程序员古德

LRU(Least Recently Used)缓存是一种常用的缓存淘汰策略,用于在有限的缓存空间中存储数据。其基本思想是:如果数据最近被访问过,那么在未来它被访问的概率也更高。因此,LRU缓存会保留最近访问过的数据,并在缓存满时淘汰最久未使用的数据

定义

【揭秘】如何使用LinkedHashMap来实现一个LUR缓存? - 程序员古德

LRU(Least Recently Used)缓存是一种常用的缓存淘汰策略,用于在有限的缓存空间中存储数据,其基本思想是,如果数据最近被访问过,那么在未来它被访问的概率也更高,因此,LRU缓存会保留最近访问过的数据,并在缓存满时淘汰最久未使用的数据,代码实现思路如下:

  1. 插入新的数据项。
  2. 访问(或检索)现有的数据项,并将其标记为最近使用。
  3. 当缓存达到其容量限制时,删除最久未使用的数据项。

代码案例

【揭秘】如何使用LinkedHashMap来实现一个LUR缓存? - 程序员古德

为了演示LRU,使用LinkedHashMap类来实现一个LUR缓存,因为它内部已经处理了哈希表和双向链表,哈希表提供了快速的插入和查找操作(平均时间复杂度为O(1)),而双向链表则维护了元素的插入顺序或访问顺序(取决于构造函数的参数),代码如下:

import java.util.LinkedHashMap;  
import java.util.Map;  
  
public class LRUCache<K, V> extends LinkedHashMap<K, V> {  
    private int cacheSize;  
  
    public LRUCache(int cacheSize) {  
        // 第三个参数设置为true表示应该按照访问顺序排序,最近访问的放在头部,最老访问的放在尾部  
        super(16, 0.75f, true); // 可以使用一个默认的初始容量,例如16  	
        this.cacheSize = cacheSize;  
    }  
  
    @Override  
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {  
        // 当map中的数据量大于指定的缓存个数的时候,就自动删除最老的数据(即尾部的数据)  
        return size() > cacheSize;  
    }  
}

在上面的代码中,LRUCache类继承了LinkedHashMap并重写了removeEldestEntry方法,这个方法的默认实现总是返回false,意味着不会自动移除最老的条目,但是在实现中,当缓存的大小超过了指定的cacheSize时,该方法返回true,触发移除最久未使用的条目(也就是链表中的尾部元素)。

此外,通过将LinkedHashMap的构造函数中的accessOrder参数设置为true,让链表按照访问顺序来排序元素,这样,最近访问的元素会被放在链表的头部,而最久未访问的元素则会被放在尾部,当需要移除元素时,可以快速地移除链表尾部的元素。

这个设计思想利用了哈希表的高效查找和链表的顺序性来实现一个简单而有效的LRU缓存,通过重写一个方法,能够定制缓存的行为以符合LRU策略。

public static void main(String[] args) {  
    LRUCache<Integer, String> lruCache = new LRUCache<>(3);  
    lruCache.put(1, "one");    // 缓存是 {1="one"}  
    lruCache.put(2, "two");    // 缓存是 {1="one", 2="two"}  
    lruCache.put(3, "three");  // 缓存是 {1="one", 2="two", 3="three"}  
    lruCache.get(1);           // 最近访问的是1,缓存是 {2="two", 3="three", 1="one"}  
    lruCache.put(4, "four");   // 因为缓存容量只有3,所以移除最老的条目2,缓存变为 {3="three", 1="one", 4="four"}  
}

核心总结

【揭秘】如何使用LinkedHashMap来实现一个LUR缓存? - 程序员古德

使用LinkedHashMap实现LRU非常简单且高效,当业务比较简单、或者用来演示LRU的实现是没有啥问题的,它本身有一些限制,因此不适合用在线上,如下:

1、它不是线程安全的,如果多个线程同时访问这个LRU缓存,可能会导致数据不一致的问题,根本在于LinkedHashMap本身并不是线程安全的,所以在多线程环境下,需要额外的同步措施,比如使用Collections.synchronizedMap方法来包装这个缓存,或者在访问时加上同步块。

2、它没办法自动处理数据加载以及数据过期,在实际应用中,有时希望当缓存中不存在请求的数据时能够自动从数据库或其他数据源加载数据,或者当数据在一定时间内没有被访问时能够自动过期。

3、它没办法精准控制内存使用,虽然可以限制缓存中的条目数量,但是这个限制并不直接对应于内存使用量,不同的缓存条目可能占用不同大小的内存,所以这个简单的LRU缓存可能会导致内存溢出,尤其是在存储大对象时。

4、它很难扩展,由于这个实现是基于LinkedHashMap的,它的扩展性受到了一定的限制,如果需要更复杂的缓存行为或更高级的功能(比如缓存分区、备份、持久化等),它是做不到的。

关注我,每天学习互联网编程技术 - 程序员古德

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

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

相关文章

Android 反编译处理Dex

前言 当我们将Android项目打包上架的时候&#xff0c;为了提高被人反编译代码的可能性可以提取 dex 文件对代码进一步做混淆处理。 本文不对相关工具做过多的解释&#xff0c;不了解的可以先熟悉相关工具的使用。 相关工具&#xff08;点击直接下载&#xff09; jadx-gui&a…

PyTorch 节省显存技巧:Activation Checkpointing

参考资料 官方文档&#xff1a; https://pytorch.org/docs/2.0/checkpoint.html官方博客&#xff1a;https://medium.com/pytorch/how-activation-checkpointing-enables-scaling-up-training-deep-learning-models-7a93ae01ff2d Activation Checkpointing 介绍 激活检查点 …

miniqmt配置

1 下载安装qmt 2 将安装目录下的 xtquant 目录复制到 python安装目录 的相同路径下 3 测试 from xtquant import xtdata def on_data (datas):#回调函数 print(datas) seq xtdata.subscribe_whole_quote(code_list[‘002306.SZ’], callbackon_data) time.sleep(10) xtda…

2023-12-15 LeetCode每日一题(反转二叉树的奇数层)

2023-12-15每日一题 一、题目编号 2415. 反转二叉树的奇数层二、题目链接 点击跳转到题目位置 三、题目描述 给你一棵 完美 二叉树的根节点 root &#xff0c;请你反转这棵树中每个 奇数 层的节点值。 例如&#xff0c;假设第 3 层的节点值是 [2,1,3,4,7,11,29,18] &…

钉钉-蓝牙打卡和平台打卡的区别

钉钉的群是部门概念。 你的账号归属到哪个群&#xff0c;就是哪个群的员工。 -------------------------------------------------------------------- 蓝牙打卡是对账号归属进行打卡的。 平台打卡是只对属于自己平台内的账号打卡的。 ----------------------------------…

cnPuTTY CAC 0.80—PuTTY CAC 0.80中文版本简单说明~~

随着PuTTY 0.80在2023-12-18发布&#xff0c;PuTTY CAC也同步进行了更新。 PuTTY CAC 0.80同步更新了针对Terrapin攻击(CVE-2023-48795)的修改&#xff0c;除了这些还进行了额外的添加和修改。另外来自cnPuTTY CAC自身也进行了小的修改。更多详细的内容请参考以下内容。 首先&…

产品经理学习-从0-1搭建策略产品

从0-1搭建策略产品 目录&#xff1a; 回顾策略产品 如何从0-1搭建策略产品 回顾策略产品 之前也了解过从产品实施的角度来看&#xff0c;策略就是针对问题的解决方案&#xff0c;在互联网时代更集中体现在2个维度&#xff1a;业务场景和数据应用 如何从0-1搭建策略产品 我们…

Python玫瑰花完整代码

文章目录 环境需求完整代码普通玫瑰花三维玫瑰花多彩玫瑰花环境需求 python3.11.4PyCharm Community Edition 2023.2.5pyinstaller6.2.0(可选,这个库用于打包,使程序没有python环境也可以运行,如果想发给好朋友的话需要这个库哦~)【注】 python环境搭建请见:https://want…

数据结构(二)栈和队列

本文是在原本数据结构与算法闯关的基础上总结得来&#xff0c;加入了自己的理解和部分习题讲解 原活动链接 邀请码: JL57F5 目录 栈和队列1.什么是栈 ?栈的入栈、出栈操作 2.什么是队列 ?队列的入队和出队 3.案例讲解 : 使用Python实现栈来管理定时任务Task 类TaskStack 类…

Spring Cloud Function SpEL注入漏洞(CVE-2022-22963)分析

一、概述 2022年3月24日&#xff0c;Pivotal修补了Spring Cloud Function中一个关键的服务器端代码注入漏洞&#xff08;Spring表达式语言注入&#xff09;&#xff0c;该漏洞有可能导致系统被攻击。Spring是一种流行的开源Java框架&#xff0c;该漏洞与另一个相关的远程代码执…

rime中州韵 help lua Translator

lua 是 Rime中州韵/小狼毫输入法强大的武器&#xff0c;掌握如何在Rime中州韵/小狼毫中使用lua&#xff0c;你将体验到什么叫 随心所欲。 先看效果 在 rime中州韵 输入效果一览 中的 &#x1f447; help效果 一节中&#xff0c; 我们看到了在Rime中州韵/小狼毫输入法中输入 h…

07-2-接口文档管理工具-swagger注解使用__ev

swagger参考demo package com.example.swagger2.controller;import com.example.swagger2.exception.SwaggerException; import com.example.swagger2.model.User; import io.swagger.annotations.*; import org.springframework.web.bind.annotation.*;import java.util.Has…

MySQL数据库索引优化

一、引言 1. 索引的重要性 MySQL数据库索引的重要性主要体现在&#xff0c;一是查询速度优化&#xff0c;索引可以极大地提高查询速度。对于没有索引的表&#xff0c;MySQL必须进行全部扫描来找到所需的行&#xff0c;如果表中数据量很大&#xff0c;那么通常很慢。通过适当的…

Python pycharm编辑器修改代码字体

在pycharm编辑器下修改代码字体&#xff0c;可以按照以下步骤&#xff1a; 点开上图所示的菜单&#xff0c; 再点击File->Settings&#xff0c;进入设置页面。 我们找到Editor下的Font并点选&#xff0c;然后我们就可以在右侧修改字体相关配置了。 这里建议使用等宽字体&…

数据结构第1章 线性表

名人说&#xff1a;莫听穿林打叶声&#xff0c;何妨吟啸且徐行。—— 苏轼《定风波莫听穿林打叶声》 本篇笔记整理&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 0、思维导图线性表1、顺序存储1&#xff09;顺序表2&…

自定义html5中日期选取器的样式

自定义html5中日期选取器的样式 1. 前言1.1 关于 h5 的新特性1.2 使用浏览器 2. html5中日期选取器默认样式3. 自定义日期样式3.1 简单定义3.2 花式样式定义 4. 改变日期格式5. 参考6. 关于低版本浏览器隐藏小三角 1. 前言 1.1 关于 h5 的新特性 可看下面的文章 HTML5 新特性之…

算法基础之能被整除的数

能被整除的数 核心思想&#xff1a; 容斥原理 总面积 1-23-4…. 总集合元素中个数 1-23-4…. #include<iostream>#include<cstring>#include<algorithm>using namespace std;const int N 20;typedef long long LL;int p[N];int main(){int n,m;cin&…

L1-075:强迫症

题目描述 小强在统计一个小区里居民的出生年月&#xff0c;但是发现大家填写的生日格式不统一&#xff0c;例如有的人写 199808&#xff0c;有的人只写 9808。有强迫症的小强请你写个程序&#xff0c;把所有人的出生年月都整理成 年年年年-月月 格式。对于那些只写了年份后两位…

Qt重载事件

重载event 事件类型 (EventType) 事件类型是 QEvent 类的一个枚举 &#xff0c;包含了 Qt 能够处理的所有不同类型的事件。这个枚举包括但不限于以下常见类型&#xff1a; QEvent::MouseButtonPress: 鼠标按钮按下事件。QEvent::MouseButtonRelease: 鼠标按钮释放事件。Q…

BikeDNA(三) OSM数据的内在分析2

BikeDNA&#xff08;三&#xff09; OSM数据的内在分析2 1.数据完整性 见上一篇BikeDNA&#xff08;二&#xff09; OSM数据的内在分析1 2.OSM标签分析 见上一篇BikeDNA&#xff08;二&#xff09; OSM数据的内在分析1 3.网络拓扑结构 本节探讨数据的几何和拓扑特征。 例…