基于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缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中的并发工具类详细解析

    Java中的并发工具类详细解析

    这篇文章主要介绍了Java中的并发工具类详细解析,CountDownLatch、 CyclicBarrier 和 Semaphore 工具类提供了一种并发流程控制的手段,Exchanger 工具类则提供了在线程间交换数据的一种手段,需要的朋友可以参考下
    2023-12-12
  • Java中的Null到底是什么

    Java中的Null到底是什么

    null是没有地址,""是有地址但是里面的内容是空的,好比做饭 null说明连锅都没有 而""则是有锅没米,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,下面我们来详细学习一下它吧
    2019-06-06
  • Java基础教程之List集合的常用方法

    Java基础教程之List集合的常用方法

    这篇文章主要给大家介绍了关于Java基础教程之List集合的常用方法,在Java编程中List集合是一种常用的数据结构,用于存储一组元素,有时候我们需要对List集合中的元素进行分组操作,即将相同属性或特征的元素归类到一组,需要的朋友可以参考下
    2023-10-10
  • 浅谈ThreadLocal为什么会内存泄漏

    浅谈ThreadLocal为什么会内存泄漏

    这篇文章主要介绍了浅谈ThreadLocal为什么会内存泄漏,每个Thread内部维护着一个ThreadLocalMap,它是一个Map,这个映射表的Key是一个弱引用,其实就是ThreadLocal本身,Value是真正存的线程变量Object,需要的朋友可以参考下
    2023-12-12
  • JdbcTemplate操作数据库的具体方法

    JdbcTemplate操作数据库的具体方法

    这篇文章主要介绍了JdbcTemplate操作数据库的具体操作方法,准备工作需要大家先导入相关的jar包,建个数据库,具体操作方法跟随小编一起看看吧
    2022-03-03
  • Java中Array List与Linked List的实现分析

    Java中Array List与Linked List的实现分析

    这篇文章主要给大家介绍了关于Array List与Linked List实现的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09
  • java JVM-clinit指令实现原理面试精讲

    java JVM-clinit指令实现原理面试精讲

    这篇文章主要介绍了java JVM-clinit指令实现原理面试精讲,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • SpringBoot多级缓存实现方案总结

    SpringBoot多级缓存实现方案总结

    所谓多级缓存,是指在整个系统架构的不同系统层面进行数据缓存,以提升访问速度,多级缓存就是为了解决项目服务中单一缓存使用不足的缺点,本文我们将给大家总结了SpringBoot多级缓存实现方案,需要的朋友可以参考下
    2023-08-08
  • Java Big Number操作BigInteger及BigDecimal类详解

    Java Big Number操作BigInteger及BigDecimal类详解

    这篇文章主要为大家介绍了Java Big Number操作BigInteger及BigDecimal类详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • java面试LruCache 和 LinkedHashMap及算法实现

    java面试LruCache 和 LinkedHashMap及算法实现

    这篇文章主要为大家介绍了java面试LruCache 和 LinkedHashMap及算法实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02

最新评论