基于LinkedHashMap实现LRU缓存

 更新时间:2023年05月05日 11:57:45   作者:JAVA旭阳  
LinkedHashMap是Java集合中一个常用的容器,它继承了HashMap, 是一个有序的Hash表。那么该如何基于LinkedHashMap实现一个LRU缓存呢?本文将介绍LinkedHashMap的实现原理,感兴趣的同学可以参考一下

概述

LinkedHashMap是Java集合中一个常用的容器,它继承了HashMap, 是一个有序的Hash表。那么该如何基于LinkedHashMap实现一个LRU缓存呢?这也是面试经常被问到的题目,主要是考察你对Java集合容器的了解程度以及LinkedHashMap的实现原理。

分析

什么是LRU?

LRU(Least Recently Used)指的是最近最少使用,是一种缓存淘汰算法,淘汰掉那个最少使用的的数据。

  • LinkedHashMap是有序的,它默认通过双向链表维护元素的插入顺序,同时,通过构造函数设置accessOrder属性为true的情况,维护元素的访问顺序,这里的访问包括插入、修改、查询等元素,每次操作都会记录顺序,所以LRU缓存其实是包括访问的,所以我们需要通过构造函数设置LinkedHashMap设置accessOrder为true。
  • 已经解决了顺序的问题,也就是最近访问的会在双向链表的尾部,最老的数据会在头部。那么如何删除头部的元素呢?其实LinkedHashMap也提供了一个回调函数removeEldestEntry,它也会在添加元素的时候调用, 默认返回false,我们可以通过重写这个方法的逻辑,如果LinkedHashMap大于缓存指定数量,就进行淘汰。

LRU缓存实现

场景:我们需要设计一个缓存最多只能存储10个元素,当元素个数超过10的时候,删除(淘汰)那些最近最少使用的数据,仅保存热点数据。

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

    /**
     * 缓存允许的最大容量
     */
    private final int maxSize;

    public LRUCache(int initialCapacity, int maxSize) {
        // accessOrder必须为true
        super(initialCapacity, 0.75f, true);
        this.maxSize = maxSize;
    }

    // 重写
    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        // 当键值对个数超过最大容量时,返回true,触发删除操作
        return size() > maxSize;
    }

    public static void main(String[] args) {
        LRUCache<String, String> cache = new LRUCache<>(5, 5);
        cache.put("1", "1");
        cache.put("2", "2");
        cache.put("3", "3");
        cache.put("4", "4");
        // 做一次查询
        cache.get("1");
        cache.put("5", "5");
        cache.put("6", "6");
        cache.put("7", "7");
        System.out.println(cache);
    }

}

运行结果:

{4=4, 1=1, 5=5, 6=6, 7=7}

因为做了一次cache.get("1"),相当于操作了1这个元素,变"新"了,所以只能淘汰3, 4。

总结

通过本文想必大家对LinkedHashMap有了更深的了解,可以用它来实现一个LRU缓存,实际上,通过LinkedHashMap实现LRU还是挺常见的,比如logback框架的LRUMessageCache。

到此这篇关于基于LinkedHashMap实现LRU缓存的文章就介绍到这了,更多相关LinkedHashMap实现LRU缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot启动过程(五)之Springboot内嵌Tomcat对象的start教程详解

    Spring Boot启动过程(五)之Springboot内嵌Tomcat对象的start教程详解

    这篇文章主要介绍了Spring Boot启动过程(五)之Springboot内嵌Tomcat对象的start的相关资料,需要的朋友可以参考下
    2017-04-04
  • 使用springMVC通过Filter实现防止xss注入

    使用springMVC通过Filter实现防止xss注入

    这篇文章主要介绍了使用springMVC通过Filter实现防止xss注入的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 深入了解Java核心类库--Date,Calendar,DateFormat类

    深入了解Java核心类库--Date,Calendar,DateFormat类

    这篇文章主要为大家详细介绍了javaDate,Calendar,DateFormat类定义与使用的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能给你带来帮助
    2021-07-07
  • java中Memcached的使用实例(包括与Spring整合)

    java中Memcached的使用实例(包括与Spring整合)

    这篇文章主要介绍了java中Memcached的使用实例(包括与Spring整合),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • idea连接数据库的操作方法

    idea连接数据库的操作方法

    这篇文章主要介绍了idea如何连接数据库,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友可以参考下
    2024-02-02
  • Java中Calendar类用法实例详解

    Java中Calendar类用法实例详解

    这篇文章主要给大家介绍了关于Java中Calendar类用法的相关资料,Calendar类是Java.util包中提供的一个抽象类,该类从JDK1.1开始出现,作为Date类的替代方案,Calendar类中包含了对不同国家地区日历的处理,需要的朋友可以参考下
    2023-09-09
  • java实现字符串和数字转换工具

    java实现字符串和数字转换工具

    这篇文章主要为大家详细介绍了java实现字符串和数字转换工具,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-04-04
  • idea使用spring Initializr 快速搭建springboot项目遇到的坑

    idea使用spring Initializr 快速搭建springboot项目遇到的坑

    这篇文章主要介绍了idea使用spring Initializr 快速搭建springboot项目遇到的坑,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • Go Java算法猜数字游戏示例详解

    Go Java算法猜数字游戏示例详解

    这篇文章主要为大家介绍了Go Java算法猜数字游戏示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • 基于feign传参MultipartFile问题解决

    基于feign传参MultipartFile问题解决

    这篇文章主要介绍了基于feign传参MultipartFile问题解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03

最新评论