Java实现LRU算法

2023-11-04

1、内存空间有限,当缓存满的时候,如何淘汰缓存?

FIFO(First In First Out)先进先出
LFU(Least Frequently Used)最不经常使用
LRU(Least Recently Used)最近最少使用

2、实现LRU demo

1、使用Java容器LinkedHashMap

LinkedHashMap本身就具有LRU算法的特性

    class LRUCache {
        private Map<Integer, Integer> cacheMap = null;

        public LRUCache(int capacity) {
            // 参数设置true,当removeEldestEntry()返回true,则删除最旧的数据
            cacheMap = new LinkedHashMap<Integer, Integer>(capacity,0.75F,true){
                @Override
                protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
                    return size() > capacity;
                }
            };
        }

        public int get(int key) {
            return cacheMap.getOrDefault(key, -1);
        }

        public void put(int key, int value) {
            cacheMap.put(key, value);
        }
    }

2、哈希表(HashMap)+双向链表

  • 维护一个双向链表,靠近链表尾部的结点是越早访问的,靠近头部的节点是最近访问的。
  • 如果此数据之前已经被缓存在链表中了,我们遍历得到这个数据对应的结点,并将其从原来的位置删除,然后再插入到链表的头部。
  • 如果此数据没有在缓存链表中,又可以分为两种情况:
    如果此时缓存未满,则将此结点直接插入到链表的头部
    如果此时缓存已满,则链表尾结点删除,将新的数据结点插入链表的头部。

在这里插入图片描述

class LRUCache2 {
        // 当前缓存容量
        private int size;
        // 限制最大缓存容量
        private int capacity;
        // 定义伪头尾节点
        private Node head;
        private Node tail;
        // 定义HashMap存储数据
        private Map<Integer, Node> cache = new HashMap();

        // 初始化操作
        public LRUCache2(int capacity) {
            size = 0;
            this.capacity = capacity;
            // 初始化头尾节点
            head = new Node();
            tail = new Node();
            // 让头尾节点相联
            head.next = tail;
            tail.pre = head;
        }

        public int get(int key) {
            Node node = cache.get(key);
            // 不存在返回-1
            if (null == node) {
                return -1;
            }
            // 存在返回值,并且将当前节点移动到头
            moveNodeHead(node);
            return node.value;
        }

        public void put(int key, int value) {
            Node node = cache.get(key);
            // 不存在则插入,插入后判断当前容量是否大于限制最大容量
            if (null == node) {
                Node newNode = new Node(key, value);
                cache.put(key, newNode);
                // 放入链表头部
                addNodeHead(newNode);
                size++;
                if (size > capacity) {
                    // 删除尾结点
                    Node tail = removeNodeTail();
                    cache.remove(tail.key);
                }
            } else {
                // 存在则覆盖value,并且将当前节点移动到头
                node.value = value;
                moveNodeHead(node);
            }
        }

        // 放入链表的头部
        private void addNodeHead(Node node) {
            // 当前头节点的下一个节点的pre和当前节点连接
            head.next.pre = node;
            //
            node.next = head.next;
            //
            head.next = node;
            node.pre = head;
        }

        // 将节点移动到链表的头部
        private void moveNodeHead(Node node) {
            node.pre.next = node.next;
            node.next.pre = node.pre;
            addNodeHead(node);
        }

        // 删除链表的尾结点
        private Node removeNodeTail() {
            Node tailNode = tail.pre;
            tailNode.pre.next = tailNode.next;
            tailNode.next.pre = tailNode.pre;
            return tailNode;
        }

        // 定义一个双向链表,实际的缓存
        class Node {
            private int key;
            private int value;
            private Node pre;
            private Node next;
            public Node() {
            }
            public Node(int key, int value) {
                this.key = key;
                this.value = value;
            }
        }
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java实现LRU算法 的相关文章

随机推荐

  • Antd中RangePicker组件弹出的日历中英混杂,月份和周显示为英问题

    在开发中需要用到antd中的RangePicker组件 但是出现了一个问题 日历中英混杂 年份是中文 月份和周都是英文 搜索了一下这个问题主要是moment造成的 可能有很多种情况 需要根据项目的自身情况来修改 首先确定一下项目中packa
  • 计算机视觉基础(十)—— HOG特征描述算子之行人检测

    本次任务将学习一种在深度学习之前非常流行的图像特征提取技术 方向梯度直方图 Histogram of Oriented Gradients 简称HOG特征 HOG特征是在2005年CVPR的会议发表 在图像手工特征提取方面具有里程碑式的意义
  • JAVA基础:线程池的使用

    目录 1 概述 2 线程池的优势 2 1 线程池为什么使用自定义方式 2 2 封装的线程池工具类有什么好处 3 线程池的七大参数 3 线程池的创建 3 1 固定数量的线程池 3 2 带缓存的线程池 3 3 执 定时任务 3 4 定时任务单线
  • Linux查看tomcat安装路径

    查看tomcat安装路径 查看tomcat安装路径 sudo find name tomcat
  • python调用c++之pybind11

    之前一直从事c 相关算法及代码的相关工作 因公司内部代码管理需要 需将算法封装待python平台使用 根据此需求 对python调用c 代码的方式进行了学习 最终综合考虑封装难度及多代码管理使用pybind11进行了相关功能的实现 pybi
  • css实现图片和文字水平居中对齐

    方式一 vertical align middle 通过vertical align middle实现现图片与文字水平对齐 需要区分html是行内元素 还是块状元素 例如 标签img span是行内元素 标签p是块状元素则需要将标签p通过d
  • 【云原生之kubernetes实战】在k8s环境下部署Halo博客系统

    云原生之kubernetes实战 在k8s环境下部署Halo博客系统 一 Halo介绍 1 Halo简介 2 Halo特点 二 环境规划 1 本次实践环境规划 2 本次实践说明 三 环境检查 1 检查工作节点状态 2 检查系统pod状态 四
  • Github注册中,邮箱验证通不过解决办法

    使用谷歌注册的时候 验证收不到消息 1 注册出现如图问题 2 在注册失败的页面 点返回的箭头 点了之后不要动 3 然后进入开启一个新的页面 复制下面的链接 进去页面 可能有点慢 等一等 OctoCaptchahttps octocaptch
  • python爬虫的学习总结

    背景 基于django框架完成jira网页数据的爬取 由于对爬虫知识知道的太少 我开始了新的学习之旅 本文前半部分都是记录这一周主要的错误 如果想直接看最终成果 可以跳到本文 成功爬取 部分浏览 学习爬虫知识 在知道了本项目可能需要爬虫后
  • C语言求解由1,2,3,4,四位数字构成的互不相同且无重复数字的四位数

    采用多重循环的方式即可 首先明确一共有四个数字供选择 组成的是四位数 那么在个 十 百 千的取值上 就只能有一位是1 一位是2 一位是3 一位是4 代码如下 include
  • 【Rust】2、实战:文件、网络、时间、进程-线程-容器、内核、信号-中断-异常

    文章目录 七 文件和存储 7 2 serde 与 bincode 序列化 7 3 实现一个 hexdump 7 4 操作文件 7 4 1 打开文件 7 4 2 用 std fs Path 交互 7 5 基于 append 模式实现 kv数据
  • 2023-9-14 最长公共子序列

    题目链接 最长公共子序列 include
  • oracle导出后 ascii编码转utf-8问题

    1 在设置如下环境变量后 从oracle中导出的中文字符为乱码 export NLS LANG AMERICAN AMERICA ZHS16GBK 2 在Linux上用file i命令查看 编码格式如下 xy w2 backimage tx
  • Mybatis-plus动态条件查询QueryWrapper的使用

    Mybatis plus动态条件查询QueryWrapper的使用 一 queryWrapper介绍 queryWrapper是mybatis plus中实现查询的对象封装操作类 可以封装sql对象 包括where条件 order by排序
  • 【Shell牛客刷题系列】SHELL6 去掉空行:来学习字符转换工具——tr命令

    该系列是基于牛客Shell题库 针对具体题目进行查漏补缺 学习相应的命令 刷题链接 牛客题霸 Shell篇 该系列文章都放到专栏下 专栏链接为 专栏 Linux 欢迎关注专栏 本文知识预告 首先学习了批量字符转换 压缩 删除的文本工具tr命
  • v-model的理解

    原理 1 展示 父组件v model 子组件接受一个props值value 将它展示到子组件自己的input上 2 改变 当子组件自身发生改变时 触发自身的input方法 然后触发父组件的事件方法 改变父组件的vaule 进而改变接受的pr
  • python作业(4)

    5 2 更多地条件测试 代码如下 str1 AAAA str2 BBBB str3 AAAA print str1 str2 str str1 str2 print str1 str3 str str1 str3 num1 10 num2
  • 蓝桥杯单片机14届记录 + 6-13届省赛代码+试题

    客观题 01 一个 8 位的 DAC 转换器 供电电压为 3 3V 参考电压 2 4V 其 1LSB 产生的输出电 压增量是 V A 0 0129 B 0 0047 C 0 0064 D 0 0094 02 IAP15F2K61S2 单片机
  • 编程实现古诗词填空

    编程实现古诗词填空登鹳雀楼 在屏募上品示 楼船 夜雪瓜洲渡 秋风大散关 请用户将缺失的汉宇 铁马 填入空白处 并在屏幕上显示完整的古诗词 楼船夜雪瓜洲渡 铁马秋风大散关
  • Java实现LRU算法

    文章目录 1 内存空间有限 当缓存满的时候 如何淘汰缓存 2 实现LRU demo 1 使用Java容器LinkedHashMap 2 哈希表 HashMap 双向链表 1 内存空间有限 当缓存满的时候 如何淘汰缓存 FIFO First