面试题目:手写一个LRU算法实现
一、常见的内存淘汰算法
FIFO 先进先出
在这种淘汰算法中,先进⼊缓存的会先被淘汰
命中率很低
LRU
Least recently used,最近最少使⽤get
根据数据的历史访问记录来进⾏淘汰数据,其核⼼思想是“如果数据最近被访问过,那么将来被访问的⼏率也更⾼”
LRU算法原理剖析

LFU
- Least Frequently Used
算法根据数据的历史访问频率来淘汰数据,其核⼼思想是“如果数据过去被访问多次,那么将来被访问的频率也更⾼”
LFU算法原理剖析
新加⼊数据插⼊到队列尾部(因为引⽤计数为1)
队列中的数据被访问后,引⽤计数增加,队列重新排序;
当需要淘汰数据时,将已经排序的列表最后的数据块删除。

- LFU的缺点
- 复杂度
- 存储成本
- 尾部容易被淘汰
二、手写LRU算法实现
利用了LinkedHashMap双向链表插入可排序
@Slf4j
public class LRUCache<K, V> extends LinkedHashMap<K, V> { private int cacheSize; public LRUCache(int cacheSize) {
super(16, 0.75f, true);
this.cacheSize = cacheSize;
} @Override
public synchronized V get(Object key) {
return super.get(key);
} @Override
public synchronized V put(K key, V value) {
return super.put(key, value);
} @Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
boolean f = size() > cacheSize;
if (f) {
log.info("LRUCache清除第三方密钥缓存Key:[{}]", eldest.getKey());
}
return f;
} public static void main(String[] args) {
LRUCache<String, Object> cache = new LRUCache<>(5);
cache.put("A","A");
cache.put("B","B");
cache.put("C","C");
cache.put("D","D");
cache.put("E","E");
System.out.println("初始化:" + cache.keySet());
System.out.println("访问值:" + cache.get("C"));
System.out.println("访问C后:" + cache.keySet());
System.out.println("PUT F后:" + cache.put("F","F"));
System.out.println(cache.keySet());
} }
main函数执行效果:

三、注意事项
LinkedHashMap有五个构造函数


//使用父类中的构造,初始化容量和加载因子,该初始化容量是指数组大小。
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
//一个参数的构造
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}
//无参构造
public LinkedHashMap() {
super();
accessOrder = false;
}
//这个不用多说,用来接受map类型的值转换为LinkedHashMap
public LinkedHashMap(Map<? extends K, ? extends V> m) {
super(m);
accessOrder = false;
}
//真正有点特殊的就是这个,多了一个参数accessOrder。存储顺序,LinkedHashMap关键的参数之一就在这个,
//true:指定迭代的顺序是按照访问顺序(近期访问最少到近期访问最多的元素)来迭代的。 false:指定迭代的顺序是按照插入顺序迭代,也就是通过插入元素的顺序来迭代所有元素
//如果你想指定访问顺序,那么就只能使用该构造方法,其他三个构造方法默认使用插入顺序。
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
参数accessOrder。存储顺序,LinkedHashMap关键的参数之一就在这个, true:指定迭代的顺序是按照访问顺序(近期访问最少到近期访问最多的元素)来迭代的。 false:指定迭代的顺序是按照插入顺序迭代,也就是通过插入元素的顺序来迭代所有元素。
如果你想指定访问顺序,那么就只能使用该构造方法,其他三个构造方法默认使用插入顺序。
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
LinkedHashMap是非线程安全的,需要加互斥锁解决并发问题。
四、思考
需要根据应用场景确定cacheSize大小,如果实际缓存数量过小,会导致缓存中的数据长期得不到刷新,为防止这种或偶发情况的发生,可配合定时任务如起一个newSingleThreadScheduledExecutor,将上面存储的value修改封装为一个对象,里面增加一个时间戳储存,每次访问实时更新,定时扫描该队列将最近30分钟未访问的key删除;还需增加一个初始进入队列的历史时间记录,将超过1小时的数据清除。
面试题目:手写一个LRU算法实现的更多相关文章
- 搞定redis面试--Redis的过期策略?手写一个LRU?
1 面试题 Redis的过期策略都有哪些?内存淘汰机制都有哪些?手写一下LRU代码实现? 2 考点分析 1)我往redis里写的数据怎么没了? 我们生产环境的redis怎么经常会丢掉一些数据?写进去了 ...
- 【redis前传】自己手写一个LRU策略 | redis淘汰策略
title: 自己手写一个LRU策略 date: 2021-06-18 12:00:30 tags: - [redis] - [lru] categories: - [redis] permalink ...
- 手写一个LRU工具类
LRU概述 LRU算法,即最近最少使用算法.其使用场景非常广泛,像我们日常用的手机的后台应用展示,软件的复制粘贴板等. 本文将基于算法思想手写一个具有LRU算法功能的Java工具类. 结构设计 在插入 ...
- 写一个LRU算法的记录
今天简单记录一下,利用Scala解答的一道LRU题目,原题为LeetCode的第146题,是一道设计LRU的题目. 题目详情 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机 ...
- 4.redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现?
作者:中华石杉 面试题 redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现? 面试官心理分析 如果你连这个问题都不知道,上来就懵了,回答不出来,那线上你写代码的时候,想当 ...
- 『练手』手写一个独立Json算法 JsonHelper
背景: > 一直使用 Newtonsoft.Json.dll 也算挺稳定的. > 但这个框架也挺闹心的: > 1.影响编译失败:https://www.cnblogs.com/zih ...
- 手写一个虚拟DOM库,彻底让你理解diff算法
所谓虚拟DOM就是用js对象来描述真实DOM,它相对于原生DOM更加轻量,因为真正的DOM对象附带有非常多的属性,另外配合虚拟DOM的diff算法,能以最少的操作来更新DOM,除此之外,也能让Vue和 ...
- java面试:手写代码
二分查找法. /** * 二分查找法:给定一组有序的数组,每次都从一半中查找.直到找到要求的数据. * 主要是得找到下标的表示方法. */ public class BinaryFind { /** ...
- 放弃antd table,基于React手写一个虚拟滚动的表格
缘起 标题有点夸张,并不是完全放弃antd-table,毕竟在react的生态圈里,对国人来说,比较好用的PC端组件库,也就antd了.即便经历了2018年圣诞彩蛋事件,antd的使用者也不仅不减,反 ...
随机推荐
- Specified cast is not valid(C#) 引发的思考(装箱,拆箱本质)
没有很华丽的语言,直接拿代码说事情把. 这段代码,会报错吗? 结论:当然不会 这段代码会报错了.原因是为啥? 这里面的水比较深.也要提醒各位写代码的适合要引起注意.异常:System.Invalid ...
- AHUACM寒假集训VI(网络流)
luoguP2472.蜥蜴 传送门 题目大意: R × C ( 1 ≤ R , C ≤ 20 ) R\times C(1\leq R,C\leq20) R×C(1≤R,C≤20)的网格上,每个格子有一 ...
- Cache写机制
Cache 写机制分为:Write-through和Write-back Write-through(直写模式) 定义:在数据更新时,同时写入缓存Cache和后端存储(主存): 优点:操作简单: 缺点 ...
- LeetCode-024-两两交换链表中的节点
两两交换链表中的节点 题目描述:给定一个链表,两两交换其中相邻的节点,并返回交换后的链表. 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换. 示例说明请见LeetCode官网. 来源:力 ...
- CoLAKE: 如何实现非结构性语言和结构性知识表征的同步训练
原创作者 | 疯狂的Max 论文CoLAKE: Contextualized Language and Knowledge Embedding 解读 01 背景与动机 随着预训练模型在NLP领域各大任 ...
- Dapr 弹性的策略
云原生应用需要处理 云中很容易出现瞬时故障.原因在以下文档 暂时性故障处理[1] 中有具体说明. 任何环境.任何平台或操作系统以及任何类型的应用程序都会发生暂时性故障. 在本地基础结构上运行的解决方案 ...
- awk讲义-1-快速入门
awk讲义-1-快速入门 一.目标问题: 1.统计各个省份中城市的数量(一维数组) 2.统计城市中区县数量,要求输出格式:省份 城市 区县数量(二维数组) 3.求两个文件的交集 4.省市和市区两个文件 ...
- laravel 框架增删改查+数据恢复
...............路由页面 //修改页面的自定义路由Route::post('unigoods/updata','uniGoodsController@updata');//数据恢复Rou ...
- 29 面向对象编程 static 关键字
补充:static 代码 // static public class Student{ private static int age; // 静态的变量 多线程 private double sco ...
- LGP7915题解
奇怪的乱搞做法(? 首先我们枚举序列的每一个位置,从这个位置劈开,假设这个位置是 \(i\),那么按照题意模拟,我们能够构造一个最终序列有 \(i\) 个 L 和 \(n-i\) 个 R 的符合题意的 ...