基于LinkedHashMap实现LRU缓存

简介: 基于LinkedHashMap实现LRU缓存

概述


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


分析


什么是LRU?

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

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

1671186280644.jpg


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。

目录
相关文章
|
1月前
|
缓存 算法 数据挖掘
深入理解缓存更新策略:从LRU到LFU
【10月更文挑战第7天】 在本文中,我们将探讨计算机系统中缓存机制的核心——缓存更新策略。缓存是提高数据检索速度的关键技术之一,无论是在硬件还是软件层面都扮演着重要角色。我们会详细介绍最常用的两种缓存算法:最近最少使用(LRU)和最少使用频率(LFU),并讨论它们的优缺点及适用场景。通过对比分析,旨在帮助读者更好地理解如何选择和实现适合自己需求的缓存策略,从而优化系统性能。
48 3
|
1月前
|
缓存 分布式计算 NoSQL
大数据-47 Redis 缓存过期 淘汰删除策略 LRU LFU 基础概念
大数据-47 Redis 缓存过期 淘汰删除策略 LRU LFU 基础概念
65 2
|
3月前
|
缓存 算法 前端开发
深入理解缓存淘汰策略:LRU和LFU算法的解析与应用
【8月更文挑战第25天】在计算机科学领域,高效管理资源对于提升系统性能至关重要。内存缓存作为一种加速数据读取的有效方法,其管理策略直接影响整体性能。本文重点介绍两种常用的缓存淘汰算法:LRU(最近最少使用)和LFU(最不经常使用)。LRU算法依据数据最近是否被访问来进行淘汰决策;而LFU算法则根据数据的访问频率做出判断。这两种算法各有特点,适用于不同的应用场景。通过深入分析这两种算法的原理、实现方式及适用场景,本文旨在帮助开发者更好地理解缓存管理机制,从而在实际应用中作出更合理的选择,有效提升系统性能和用户体验。
186 1
|
4月前
|
缓存 Python
在Python中,`functools`模块提供了一个非常有用的装饰器`lru_cache()`,它实现了最近最少使用(Least Recently Used, LRU)缓存策略。
在Python中,`functools`模块提供了一个非常有用的装饰器`lru_cache()`,它实现了最近最少使用(Least Recently Used, LRU)缓存策略。
|
3月前
|
存储 缓存 Java
|
3月前
|
存储 缓存 算法
Python 从零开始实现一个简单的LRU缓存
Python 从零开始实现一个简单的LRU缓存
42 0
|
4月前
|
缓存 算法 前端开发
前端 JS 经典:LRU 缓存算法
前端 JS 经典:LRU 缓存算法
94 0
|
1月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(一)
数据的存储--Redis缓存存储(一)
|
1月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
74 6
|
8天前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题