算法学习笔记(10)-缓存淘汰算法LRU

LRU算法–缓存淘汰算法 LRU算法–缓存淘汰算法目录LRU算法缓存淘汰算法目录 什么是 LRU LRU 算法思想 为什么需要页面置换算法 分页原理图 假设使用 FIFO 先进先出 实现页面置换算法 LRU 算法原理图 使用双向链表实现LRU算法 Clock算法是公认的很好的近似LRU的算法1. 什么是 LRULRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是 阅读详情

今日心情美丽,让咱们看看传说中的LRU算法是怎么一回事

1.1 何谓LRU算法

LRU算法指的是Least Recently Used,即最近最少使用算法,也被称作缓存淘汰算法/页面置换算法,LRU算法的基本原则是如果一个数据最近很少被访问到,那么之后也应该很少被访问到;如果一个数据最近经常被访问到,那么置换也应该经常被访问到.

1.2 如何实现

实现LRU算法一般有以下几种做法:

  • 双向链表实现
    通过双向链表链表可以实现一个LRU缓存结果,做法是

    1.新添加的数据放置在链头
    2.将被访问到的数据移动到链头
    3.当链表满载时,将链尾数据丢弃

    如图,通过这三步就可以将经常被访问到的数据放置在链头,从而在下次访问时减少从头至尾的对比时间;而不经常被访问的数据则放置在链尾,当链表满载时,将其删除:

[外链图片转存失败(img-zmQ9Eoz8-1567614666654)(picture/LRU.png)]

代码实现

/**
 * @Auther: ARong
 * @Date: 19-9-5 上午00:26
 * @Description: 基于双向链表和HashMap的LRU算法实现
 **/
public class LRUCache<K, V> {
    //链头
    private Node head;
    //链尾
    private Node end;
    //链表所容纳的数据量16
    private  int capacity;
    //存储Node的HashMap
    HashMap<K, Node> map = new HashMap<>();

    //构造方法中指定容量
    public LRUCache(int capacity) {
        this.capacity = capacity;
    }
    public LRUCache() {
        this.capacity = 16;
    }

    //双向链表节点
    class Node {
        Node pre;
        Node next;
        K key;
        V value;

        Node(K key, V value) {
            this.key = key;
            this.value = value;
        }
    }

    /**
     * @auther: Arong
     * @description: 添加缓存数据
     * @param: key value
     * @return: void
     * @date: 19-9-5 上午00:26
     */
    public void add(K key, V value) {
        //检查是否需要删除尾部元素
        check();
        //分情况在链头添加数据
        if (map.containsKey(key)) {
            //map中含有该缓存,更新其value,并将其置于链表首部
            Node node = map.get(key);
            node.value = value;
            removeNode(node);
            putHead(node);
        } else {
            //map中不含有该数据,直接添加到map中和链表头部即可
            Node node = new Node(key, value);
            map.put(key, node);
            putHead(node);
        }
    }
    /**
     * @auther: Arong
     * @description: 将Node置于链表头部
     * @param: [node]
     * @return: void
     * @date: 19-9-5 上午00:26
     */
    private void putHead(Node node) {
        if (node == end) {
            end = node.pre;
        }
        if (end == null) {
            end = node;
        }
        node.pre = null;
        node.next = head;
        if (head != null) {
            head.pre = node;
        }
        head = node;
    }

    /**
     * @auther: Arong
     * @description: 检查是否需要删除尾部数据
     * @param: []
     * @return: void
     * @date: 19-9-5 上午00:26
     */
    private void check() {
        if (map.size() == capacity) {
            //需要删除尾部元素
            removeNode(end);
        }
    }



    /**
     * @auther: Arong
     * @description: 获取缓存数据
     * @param: [key]
     * @return: V
     * @date: 19-9-5 上午00:26
     */
    public V get(K key) {
        //在链表中搜索该数据
        if (map.containsKey(key)) {
            //将其V返回.并且将Node置于链头
            Node node = map.get(key);
            removeNode(node);
            putHead(node);
            return node.value;
        } else {
            return null;
        }
    }

    /**
     * @auther: Arong
     * =@description: 删除缓存
     * @param: [key]
     * @return: V
     * @date: 19-9-5 上午00:26
     */
    public V remove(K key) {
        if (map.containsKey(key)) {
            Node node = map.get(key);
            map.remove(key);
            removeNode(node);
            return node.value;
        } else {
            return null;
        }
    }

    /**
     * @auther: Arong
     * @description: 删除节点
     * @param: [node]
     * @return: void
     * @date: 19-9-5 上午00:26
     */
    private void removeNode(Node node) {
        if (node.pre != null) {
            node.pre.next = node.next;
        } else {
            head = node.next;
            head.pre = null;
        }

        if (node.next != null) {
            node.next.pre = node.pre;
        } else {
            end = node.pre;
        }
    }

}

1.3 为何不直接使用HashMap作为LRU底层结构

1.若不限定HashMap的容量,那么至多可以存储2^30个缓存数据,但是多于这个就无法再存入数据,并且缓存数据过多,内存占用巨大会产生OOM问题; 2.若限定HashMap的容量,例如限定为16,使用put时还可以直接放入HashMap中,但若数量超过了16,由于无法记录哪个数据被访问到得最少,那么就无法删去数据,也就无法做到动态地维持容量平衡;

1.4 基于LinkedHashMap实现LRUCache

下面介绍一种实现LRU的更简单的方式,它基于java.util.LinkedHashMap,LinkedHashMap底层采用的就是上文中链表+HashMap的实现,原理和上文一致:

public class LRUCacheByLinkedHashMap<K, V> extends LinkedHashMap<K, V> {

    private int capacity;

    public LRUCacheByLinkedHashMap(int capacity) {
        super(capacity, 0.75f, true);
        this.capacity = capacity;
    }

    /**
     * @auther: Arong
     * @description: 重写删除最后访问元素的方法
     * @param: [eldest]
     * @return: boolean
     * @date: 下午6:52 19-9-5
     */
    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        //LinkedList在每次get时会调用该方法去判断需不需要删除最久没有被访问到的元素,返回true则删除
        return super.size() > capacity;
    }

    /**
     * @auther: Arong
     * @description: 添加元素
     * @param: [key, value]
     * @return: void
     * @date: 下午6:49 19-9-5
     */
    public void add(K key, V value) {
        super.put(key, value);
    }
手撕LRU和LFU缓存淘汰算法 LFU()算法是一种用于缓存替换的算法,其思想是淘汰最少被使用的缓存数据。它的基本原理是根据每个数据块的使用频率来决定其是否被淘汰。LFU算法主要用于高速缓存中,以保证缓存空间的高效利用。LFU算法的实现需要一个计数器来记录每个数据块被使用的次数,当缓存空间满了时,选择使用频率最低的数据块进行替换。如果多个数据块的使用频率相同,则选择最早使用的数据块进行替换。LFU算法的优点在于它能够较好地适应不同访问模式下的缓存需求,并且能够保证缓存空间的高效利用。 阅读详情

相关推荐

LRU缓存淘汰算法

 来源公众号:算法面试题 简介   LRU,最近最少使用算法,即当要对数据进行淘汰时,先将最近最久未使用的数据淘汰(亦说最近最久未使用算法),是一种缓存淘汰算法。     意义:大家知道计算机的内存是有限的,当我们对一些数据一直缓存而不淘汰的话,那么内存总会被占满的,特别是服务器,造成的后果是可怕的。   应用场景:内存的页面淘汰、站内搜索关键字的缓存淘汰(详见:《如何应对...

Great_Eagle的博客 2879

LRU的实现

一、什么是缓存 这里说的缓存是一种广义的概念,在计算机存储层次结构中,低一层的存储器都可以看做是高一层的缓存。比如Cache是内存的缓存,内存是硬盘的缓存,硬盘是网络的缓存等等。 缓存可以有效地解决存储器性能与容量的这对矛盾,但绝非看上去那么简单。如果缓存算法设计不当,非但不能提高访问速度,反而会使系统变得更慢。 从本质上来说,缓存之所以有效是因为程序和数据的局部性(locality)。程序...

轻描时光 1730

常用缓存淘汰算法LFU、LRU、2Q、ARC

常用缓存淘汰算法LFU、LRU、2Q、ARC、FIFOLFULRU LFU LRU

惜暮 3145

近期最少使(LRU)算法

一、LRU算法是什么? LRU:Least Recrntly Used,近期最少使用; LRU算法用于cache管理或者任何需要对访问权进行周期更新的场景;基于时间和空间考虑,cache中存储着近期将会使用到的数据。当cache满后,如果有新的数据到来,需要将某个现有的数据从cache中清除,为新数据提供空间。LRU算法可以找到最久未被使用过的数据,cache将此数据清除,并将新数据写入到此处。 二、LRU算法实现 1.LRU算法原理 在RTL中实现LRU算法的方法有很多种。一种采用硬件实现LRU的方法是矩

m0_38027762的博客 2794

web技术分享| LRU 缓存淘汰算法

了解 LRU 之前,我们应该了解一下缓存,大家都知道计算机具有缓存内存,可以临时存储最常用的数据,当缓存数据超过一定大小时,系统会进行回收,以便释放出空间来缓存新的数据,但从系统中检索数据的成本比较高。 缓存要求: 固定大小:缓存需要有一些限制来限制内存使用。 快速访问:缓存插入和查找操作应该很快,最好是 O(1) 时间。 在达到内存限制的情况下替换条目:缓存应该具有有效的算法来在内存已满时驱逐条目 如果提供一个缓存替换算法来辅助管理,按照设定的内存大小,删除最少使用的数据,在系统回收之前主动释放出空间

anyRTC的博客 1678

聊聊缓存淘汰算法-LRU 实现原理

前言 我们常用缓存提升数据查询速度,由于缓存容量有限,当缓存容量到达上限,就需要删除部分数据挪出空间,这样新数据才可以添加进来。缓存数据不能随机删除,一般情况下我们需要根据某种算法删除缓存数据。常用淘汰算法有 LRU,LFU,FIFO,这篇文章我们聊聊 LRU 算法。 LRU 简介 LRU 是 Least Recently Used 的缩写,这种算法认为最近使用的数据是热门数据,下一次很大概率将会...

楼下小黑哥 1668

LRU Cache 最近最少使用缓存算法

LRU Cache 最近最少使用缓存算法

栾金鹿 634

如何实现LRU缓存淘汰算法?

在计算机科学中,LRU(Least Recently Used)缓存淘汰算法是一种常用的策略,用于管理有限的缓存空间。当缓存已满时,LRU 算法会淘汰最近最少使用的数据,以腾出空间来存储新的数据。本文将详细介绍如何实现 LRU 缓存淘汰算法。LRU 算法的核心思想是:当需要淘汰数据时,选择最近最少使用的数据进行淘汰。这意味着,最近被访问的数据在缓存中的生存时间最长,而长时间未被访问的数据则更容易被淘汰。例如,假设有一个缓存空间可以存储三个数据项。一开始,缓存为空。当依次访问数据项 A、B、C 时,缓存中存储

yonggeit的博客 3243

LRU(最近最少使用)缓存机制

title: LRU缓存机制 categories: 操作系统 tags: 操作系统 LRU OS 计算机知识 LRU(最近最少使用)缓存机制 LRU:最近最少使用缓存机制 其设计的原则依据:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。 假定系统为某进程分配了3个物理块,进程运行时的页面走向为 7 0 1 2 0 3 0 4,开始时3个物理块均为空,那么LRU算法是如下工作的: 上述操纵通过一个.

StriveZs'Blog 727

Hopf振荡器在机器人步态控制里到底怎么用?一个CPG仿生案例说清楚

本文深入解析了Hopf振荡器在机器人步态控制中的实际应用,通过CPG仿生案例详细展示了从数学方程到关节指令的完整流程。重点探讨了Hopf振荡器的极限环稳定性、参数调节技巧及自适应控制策略,为机器人运动控制提供了高效解决方案。

weixin_29284657的博客 203

IGS精密星历高效获取与解析指南

本文详细介绍了IGS精密星历在高精度定位中的核心作用,对比了IGS Final、IGR和IGU等不同产品的精度与时效性差异。指南提供了从武汉大学、NASA CDDIS等数据中心高效下载数据的实战方法,并深入解析了SP3文件格式,帮助用户掌握精密星历的获取、解析与自动化处理技巧,以支持厘米级定位应用。

garlic的博客 839

LRU算法

LRU算法:最近最少使用算法。大意就是根据最近访问的记录,对缓存的数据进行淘汰。如果一个数据最近被访问,或经常访问。则把数据放到列表的前面,而数据很久未访问,或者访问率较低,就会被放在后面,在列表内存不足的时候,将其移除缓存列表。 #include <iostream> #include <unordered_map> #include <algorithm> using namespace std; //双向链表结构 struct DLinkedNode { //保

blame_的博客 272

常见的数值积分方法 (欧拉、中值、龙格-库塔,【常用于IMU中】)

1. 积分基本概念 设F(x)为函数f(x)的一个原函数,我们把函数f(x)的所有原函数F(x)+C(C为任意常数)叫做函数f(x)的不定积分(indefiniteintegral)。 非线性微分方程: 在有限的时间间隔Δt积分: 连续时间内积分: 工程上最常见的有三种:欧拉积分(Euler method)、中值积分(Midpoint method)和龙格-库塔法积分(Runge–Kutta methods)。他们的区别就是如何用数值方法模拟一个斜率。这里简单总结如下: ...

努力努力努力 2万+

Redis缓存淘汰算法——LRU

LRU算法原理分析,手写LRU示例,redis中的lru

m0_62909831的博客 2278

C++ getline函数详解与示例代码

每次调用函数时,会读取一行文本,并将其存储在字符串对象中。在循环中,我们检查读取到的文本是否为空行,如果是则跳出循环,否则输出读取到的文本。这个函数在处理用户输入、文件读取等场景中非常有用,希望能对您的C++编程有所帮助。函数是一个常用的字符串输入函数,可以用于从输入流中读取一行文本。首先,我们输出提示信息,要求用户输入一行文本。函数会等待用户输入,并将输入的文本存储在。函数从输入流中读取一行文本,并将其存储在字符串对象。这样,当用户输入制表符时,函数会停止读取。函数的用法,并提供相应的示例代码。

LogicGuruX的博客 829

QT Android开发之Android端usb调试模式设置与问题解决

QT Android开发之Android端usb调试模式设置与问题解决 一.QT android开发android端usb调试模式设置 QT android开发环境搭建完成后,android设备需要打开usb调试模式才能正常连接,下面以小米ipad为例进行设置(其他手机和ipad设置方法类似) 二.小米ipad打开usb调试模式 1.设置----我的设备-----全部参数信息-----OS版本---点击这里6次以上就进入开发者模式。

热土程序园,利他愉己~ 1133

LRU 和 LFU 缓存淘汰策略

缓存淘汰算法

Victorgcx的博客 2310

打通ZYNQ的任督二脉:AXI_FIFO数据交互全解析

FIFO(First In First Out,先进先出)是一种经典的数据缓冲结构,就像排队买票一样,先来的人先得到服务。时钟域交叉(CDC):连接不同时钟频率的模块数据缓冲:平衡生产者和消费者的速度差异流量控制:防止数据丢失或溢出input clk,// 输入AXI4-Stream接口(从PS到PL)// 输出AXI4-Stream接口(从PL到PS)// 状态指示信号// 定义状态机状态// 数据缓存// 8个深度的缓存// 流水线处理寄存器。

QQ_778132974的博客 307

缓存淘汰算法之LRU

1.LRU1.1.原理 LRU(Leastrecentlyused,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。 1.2.实现 最常见的实现是使用一个链表保存缓存数据,详细算法实现如下: 1.新数据插入到链表头部; 2.每当缓存命中(即缓存数据被访问),则将数据移到链表头部; 3.当链表满...

weixin_30596165的博客 4525

vue3:最新实现腾讯人脸核身+增强版人脸核身使用方法及示例源码,Vue3如何使用腾讯云慧眼人脸核身,提供人脸核身案例、身份信息核验、活体检测与核身比对等示例代码(后端spring与thinkphp)

vue3接入腾讯人脸核身,腾讯云人脸核身Vue3+后端代码,H5人脸核身,vue3 H5如何使用腾讯人脸核身sdk,vue3+thinkphp腾讯人脸核身,Spring Boot接入腾讯云人脸核身教程,hinkphp腾讯人脸核身,vue3人脸核身插件接入流程,vue+spring boot实现腾讯人脸核身,vue3接入腾讯云【增强版人脸核身接入】,vue3 h5微信公众号网页腾讯云慧眼人脸核身,tvue3接入人脸核身SDK,vue3+typescrip+vite接入慧眼实名认证,vue3腾讯云活体人脸核身(

✅ 精选推荐文章 4121

【人工智能】Spring AI项目在定义 `response_format` 的 Invalid schema for response_format ‘custom_schema‘

确保。

奶爸的编程之路,也就一周冷个三天 562

缓存淘汰算法(LRU)

1. LRU 1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。 1.2. 实现 最常见的实现是使用一个链表保存缓存数据,详细算法实现如下: \1. 新数据插入到链表头部; \2. 每当缓存命中(即缓存数据被访问),则将数据移到链表头部; \3. 当链表满的时候,将链表尾部的数据丢弃。 1.3. 分析 【命中率】 当存在热点数据时,LRU的效率很好,但

Arlssaze的博客 3419

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

java实现LRU缓存淘汰算法

LRU算法:最近最少使用淘汰算法(Least Recently Used)。LRU是淘汰最长时间没有被使用的缓存(即使该缓存被访问的次数最多)。 代码如下: import java.util.*; public class LRUCache { int cap;//最大缓存的数量 Map<String, String> values;//缓存 Set<String> position;//缓存的key,按照存入的顺序存储 public LRUCa

西凉的悲伤博客 3425

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Java实现LRU缓存淘汰算法

当accessOrder为true时,链表按照访问顺序排序,最近访问的元素会被放到尾部,最老访问的元素在头部。例如,如果我们知道缓存的键(key)是小整数或者可以映射到小整数的对象(如枚举类型),我们可以使用数组来实现一个更高效的LRU缓存。但是需要注意的是,由于LinkedHashSet并没有提供直接访问元素的方法,我们需要遍历整个集合才能找到最久未使用的元素。在实现LRU缓存时,我们可以使用LinkedHashSet来存储缓存中的元素,然后再使用一个HashMap来存储元素到访问时间的映射。

让每一行代码都有改变世界的力量 1148

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

缓存淘汰算法LRU

1 概述 LRU(Least Recently Used)算法是一种缓存淘汰算法,当系统的缓存过大,达到删除缓存的阀值时,最先删除最久没有被使用过的数据,被用于操作系统和Redis数据库中。 LRU的底层是由哈希算法+链表组成的。哈希算法具有查找高效的优点,却没法保存添加顺序,因此采用链表记录数据的使用顺序。说白了就是数据被存为两份,哈希和链表各一份。在没有达到缓存上限时候,它两相安无事,当达到缓存上限时,根据链表中保存的使用顺序进行删除。 2 图解数据移动顺序 假设系统缓存的上限为3个节点 2.1 向缓存

JayLaiSCUT的博客 3142

LRU动态淘汰缓存算法

构成“哈希链表”:借助哈希表赋予链表快速查找的特性:可以快速查找某个 key 是否存在缓存(链表)中,同时可以快速删除、添加节点。

weixin_62290551的博客 1032
上一篇: Java基础(9)-反射与动态代理
下一篇: 数据结构(10)-TrieTree(字典树)的实现
BoringRong
BoringRong 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 2万+粉丝 386原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BoringRong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值