使用LinkedHashMap实现LRU算法

使用LinkedHashMap实现LRU算法

LRU算法,最近最少使用原则,如果要实现该算法,可以借助LinkedHashMap数据结构,LinkedHashMap继承HashMap,底层使用哈希表和双向链表来保存所有元素,使用LinkedHashMap可以确保元素按照顺序进行存储。

默认情况下,LinkedHashMap是按照元素的添加顺序存储,也可以启用按照访问顺序存储,即最近读取的数据放在最前面,最早读取的数据放在最后面,然后它还有一个判断是否删除最老数据的方法,默认是返回false,即不删除数据。

下面就基于这两种存储方式,简单展示一下如何实现LRU算法:

 

一、基于按添加顺序存储的方式实现LRU:

public class LRUTest
{
    int capacity;
    LinkedHashMap<Integer, Integer> cache;

    LRUTest(int capacity)
    {
        cache = new LinkedHashMap<>();
        this.capacity = capacity;
    }

    //访问元素
    public int get(int key)
    {
        if(!cache.containsKey(key))
        {
            return -1;
        }

        //存在,先从链表头部删除删除,在插入到链表尾部
        int val = cache.get(key);
        cache.remove(key);
        cache.put(key, val);

        return val;
    }

    //添加元素
    public void put(int key, int val)
    {
        if(cache.containsKey(key))
        {
            cache.remove(key);
        }

        //如果链表已经满了,则删除头部节点
        if(cache.size() == capacity)
        {
            Set<Integer> keySet = cache.keySet();
            Iterator<Integer> iterator = keySet.iterator();
            cache.remove(iterator.next());
        }

        cache.put(key, val);
    }
}

 

二、基于按访问顺序存储的方式实现LRU:

该方式的核心就是继承LinkedHashMap,并设置LinkedHashMap的accessOrder参数为true,然后重写LinkedHashMap的removeEldestEntry()方法。

public class LRUTest extends LinkedHashMap<String, String>
{
    private int capacity;

    /**
     * 当LinkedHashMap的accessOrder参数为true时,即会按照访问顺序排序,最近访问的放在最前,最早访问的放在后面
     */
    public LRUTest(int capacity) {
        super(16, 0.75f, true);
        this.capacity = capacity;
    }

    /**
     * LinkedHashMap自带的判断是否删除最老的元素方法,默认返回false,即不删除老数据
     */
    @Override
    protected boolean removeEldestEntry(Map.Entry<String, String> eldest)
    {
        return size() > capacity;
    }
}

测试方法:

    public static void main(String[] args)
    {
        Map<String, String> linkedHashMap = new LRUTest(6);

        linkedHashMap.put("1", "1");
        linkedHashMap.put("2", "2");
        linkedHashMap.put("3", "3");
        linkedHashMap.put("4", "4");
        linkedHashMap.put("5", "5");
        linkedHashMap.put("6", "6");
        linkedHashMap.put("7", "7");
        linkedHashMap.put("8", "8");
        linkedHashMap.put("9", "9");

        System.out.println("size="+linkedHashMap.size());
        System.out.println(linkedHashMap.get("8"));

        linkedHashMap.forEach((k,v) ->{
            System.out.print(k + ":"+ v +"  ");
        });

        System.out.println();
        System.out.println("size="+linkedHashMap.size());
    }

输出结果:

size=6
8
4:4  5:5  6:6  7:7  9:9  8:8  
size=6

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/100026.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ActiveMQ之ActiveMQ-CPP安装及测试

    在介绍ActiveMQ-CP之前,先介绍下CMS(C++MessagingService),CMS是C++程序与消息中间件进行通信的一种标准接口,可以通过CMS接口与类似ActiveMQ这样的消息

    2021年12月29日
    78
  • ssl协议及开源实现openssl

    ssl协议及开源实现opensslssl协议SSL:(SecureSocketLayer)安全套接层,ssl是一套安全协议,被应用层调用,当http调用ssl协议时被称为https,当ftp调用ssl协议时被称为sftp。lls是一个协议的集合,其中包括:Handshake协议:包括协商安全参数和密码套件、服务器身份认证(客户端身份认证可选)、密钥交换ChangeCipherSpec协议:一条消息表明握手协议已

    2022年5月11日
    65
  • Spyder python 多行注释快捷键

    Spyder python 多行注释快捷键Spyderpython 多行注释快捷键多行注释 第一步 选中需要注释的内容第二步 两种选择 ctrl 1 解除注释需要再次选中代码 然后按 ctrl 1 效果 N STATES 15 ACTIONS left right EPSILON 0 9 ALPHA 0 1ctrl 4 块注释 解除注释需要再次选中代码 然后按 ctrl 5 效果

    2025年11月22日
    3
  • matlab画三维图形_matlab的三维函数

    matlab画三维图形_matlab的三维函数对散点图拟合三维网格图形:num=xlsread(‘data_2011a.xls’,’B4:E322′)//读取出该区域的数据作为表格A=num(:,1)//从B矩阵取出第一列的所有行B=num(:,2)C=num(:,3)xx=linspace(min(A),max(A),50);//产生min(A)到max(A)均摊的50个点,目的上拟合离散点数量上的不足yy=linsp…

    2022年10月11日
    3
  • python编程的文件后缀是什么_文件没后缀名怎么批量加后缀

    python编程的文件后缀是什么_文件没后缀名怎么批量加后缀python文件后缀名总结:(1).py:这通常是您编写的输入源代码。(2).py3:Python3脚本(Python3脚本通常以.py而不是.py3结尾,很少使用)。(3).pyc:这是编译好的字节码。如果导入一个模块,python将生成一个*.pyc包含字节码的文件,以便再次导入它更容易(也更快)。.pyc二进制文件可以反编译成.py文件,反编译软件叫EasyPythonDecompile…

    2025年11月27日
    2
  • db2排序rownumber函数讨论[通俗易懂]

    db2排序rownumber函数讨论[通俗易懂] 在我的应用中使用了Rownumber函数,由于我的非正常理解造成了排序混乱。现在晒出来讨论。一、初识rownumberrownumber()函数允许开发人员动态地将行号指定给结果集。如果去掉row_next子句(ROW_NEXTBETWEEN?and?),那么将返回所有匹配选择标准的行。上面使用的SELECT*FROM子句可以看作一个临时表,里面存有匹配选

    2022年6月6日
    147

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号