【面试题】LRU算法及编码实现LRU策略缓存
概念
LRU(least recently used)就是将最近不被访问的数据给淘汰掉,LRU基于一种假设:认为最近使用过的数据将来被使用的概率也大,最近没有被访问的数据将来被使用的概率比较低。
原理
LRU一般通过链表形式来存放缓存数据,新插入或被访问的数据放在链表头部,超过一定阈值后,自动淘汰链表尾部的数据。下图很形象的说明了LRU缓存淘汰过程。(图片来自网络)

步骤:
1、新插入A, 将A放置在队列头部
2、新插入B, 将B放置在队列头部, A自动推举次席。
3、新插入C, 将C放置在队列头部, B自动推举次席。
4、新插入D, 将D放置在队列头部, C自动推举次席。
5、新插入E, 将E放置在队列头部, D自动推举次席。
6、新插入E, 将E放置在队列头部, 这时队列长度大于阈值,自动将尾部数据A给淘汰掉
7、访问数据C,然后将C重新放置在队列头部。
8、新插入E, 将E放置在队列头部, 这时队列长度大于阈值,自动淘汰尾部数据B
编码实现LRU策略缓存
/**
* 2018/4/11.
*
* 使用链表+hashmap来实现, 这里没有考虑并发情况, 所以在代码中没有使用锁
*/
public class LRUCache<K, V> { class CacheNode {
public CacheNode before;
public Object key;
public Object value;
public CacheNode after; public CacheNode() {
}
} private HashMap<K, CacheNode> caches;
private int maxCapacity;
private int currentCacheSize;
/**
* 头结点, 头结点不参与淘汰,只是作为标识链表中的第一个节点
*/
private CacheNode head;
/**
* 尾节点, 尾节点不参与淘汰, 只是作为标识链表中最后一个节点
*/
private CacheNode tail; public LRUCache(int maxCapacity) {
this.maxCapacity = maxCapacity;
caches = new HashMap<>(maxCapacity);
head = tail = new CacheNode();
head.after = tail; //对head 的after节点赋值, 防止后续操作出现空指针异常
tail.before = head; // 对tail的before节点赋值, 防止后续操作出现空指针异常
} public void put(K k, V v) {
CacheNode node = caches.get(k);
if (node == null) {
if (currentCacheSize >= maxCapacity) {
caches.remove(tail.before.key); //淘汰尾部的元素
removeLast();
} node = new CacheNode();
node.key = k; currentCacheSize ++;
} node.value = v;
moveToFirst(node); // LRU策略, 新插入的元素放置到队列头部
caches.put(k, node);
} public void moveToFirst(CacheNode node) {
CacheNode n = head.after;
head.after = node;
node.before = head;
n.before = node;
node.after = n;
} public void removeLast() {
CacheNode n = tail.before.before;
n.after = tail;
tail.before = n;
} public Object get(K k) {
CacheNode node = caches.get(k);
if (node == null) {
return null;
} Object v = node.value;
moveToFirst(node);
return v;
} public Object remove(K k) {
CacheNode node = caches.get(k);
if (node == null) {
return null;
} CacheNode pre = node.before;
CacheNode next = node.after;
pre.after = next;
next.before = pre; caches.remove(k); currentCacheSize --;
return node.value;
}
}
上述代码在博主本机测试验证通过(单线程操作下)
【面试题】LRU算法及编码实现LRU策略缓存的更多相关文章
- redis的LRU算法(一)
最近加班比较累,完全不想写作了.. 刚看到一篇有趣的文章,是redis的作者antirez对redis的LRU算法的回顾.LRU算法是Least Recently Used的意思,将最近最少使用的资源 ...
- 【算法】LRU算法
缓存一般存放的都是热点数据,而热点数据又是利用LRU(最近最久未用算法)对不断访问的数据筛选淘汰出来的. 出于对这个算法的好奇就查了下资料. LRU算法四种实现方式介绍 缓存淘汰算法 利用Linked ...
- LRU算法与LRUCache
关于LRU LRU(Least recently used,最近最少使用)算法是操作系统中一种经典的页面置换算法,当发生缺页中断时,需要将内存的一个或几个页面置换出,LRU指出应该将内存最近最少使用的 ...
- 基于LinkedhashMap实现的LRU算法
LRU全称是Least Recently Used,即最近最久未使用的意思.LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小.也就是说,当限定的空间已存 ...
- Guava---缓存之LRU算法
随笔 - 169 文章 - 0 评论 - 292 GuavaCache学习笔记一:自定义LRU算法的缓存实现 前言 今天在看GuavaCache缓存相关的源码,这里想到先自己手动实现一个LRU ...
- 【Redis 设置Redis使用LRU算法】
转自:http://ifeve.com/redis-lru/ 本文将介绍Redis在生产环境中使用的Redis的LRU策略,以及自己动手实现的LRU算法(php) 1.设置Redis使用LRU算法 L ...
- Redis内存回收:LRU算法
Redis技术交流群481804090 Redis:https://github.com/zwjlpeng/Redis_Deep_Read Redis中采用两种算法进行内存回收,引用计数算法以及LRU ...
- FIFO调度算法和LRU算法
一.理论 FIFO:先进先出调度算法 LRU:最近最久未使用调度算法 两者都是缓存调度算法,经常用作内存的页面置换算法. 打一个比方,帮助你理解.你有很多的书,比如说10000本.由于你的书实在太多了 ...
- LRU算法原理解析
LRU是Least Recently Used的缩写,即最近最少使用,常用于页面置换算法,是为虚拟页式存储管理服务的. 现代操作系统提供了一种对主存的抽象概念虚拟内存,来对主存进行更好地管理.他将主存 ...
随机推荐
- 【插件开发】—— 8 IPreferenceStore,插件的键/值存储!
前文回顾: 1 插件学习篇 2 简单的建立插件工程以及模型文件分析 3 利用扩展点,开发透视图 4 SWT编程须知 5 SWT简单控件的使用与布局搭配 6 SWT复杂空间与布局搭配 7 SWT布局详解 ...
- 【笔记】对自定义异常的理解(Java)
原本,原有的异常是非手动地.自动地抛出的. 了解自定义异常时,发现其信息只是: 继承了谁,即它自己算哪种异常: 它的信息,比如一个ID,这个貌似还是可选的: 它是可被传入信息的 没有遗漏的话,就这仨了 ...
- 《Windows核心编程系列》十三谈谈在应用程序中使用虚拟内存
在应用程序中使用虚拟内存 Windows提供了以下三种机制对内存进行操控: 一:虚拟内存.最适合来管理大型对象数据或大型结构数组. 二:内存映射文件.最适合用来管理大型数据流,以及在同一机 器上运行的 ...
- poj 2506 Tiling 递推
题目链接: http://poj.org/problem?id=2506 题目描述: 有2*1和2*2两种瓷片,问铺成2*n的图形有多少种方法? 解题思路: 利用递推思想,2*n可以由2*(n-1)的 ...
- 题解报告:hdu 1754 I Hate It(线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某 ...
- java getDocumentBase() 得到的文件夹路径
参考一个百度知道上的回答 举例说来,假设你的项目文件是xx,而这个xx文件夹是在D盘下的yy文件夹里,即项目文件的完整路径D:\yy\xx,则编译运行文件后,在xx文件夹里会产生名为build的文件夹 ...
- 总结用CoreText绘制文本时遇到的问题以及解决办法
关于CoreText不做解释.用的人自然知道这个是干什么的. 功能非常强大,可以绘制文本,图片等. 这次用的Xcode7.0的版本.所以之前很多方法,现在不能用.也不是不能用,就是有黄色警告很不爽. ...
- 关于线程间操作无效: 从不是创建控件“xx”的线程访问它,错误解决方法(自定义委托和系统委托Action或Func解决)
这是一个线程不安全的问题.跨线程操作问题. 比如我们需要在线程中改变textbox的文本,textbox的name是txtShowMsg 第一种方法(不推荐使用) 在窗体构造函数中写Control.C ...
- Pycharm+Django+Python+MySQL开发 后台管理数据库
Django框架十分简单易用,适合搭建个人博客网站.网上有很多教程,大多是关于命令行操作Django,这里分享一些用最新工具进行Django开发过程,主要是PyCharm太强大,不用有点可惜. 第一次 ...
- web安全后渗透--XSS平台搭建及使用
xss平台搭建 1.申请一个云主机来进行建站:149.28.xx.xx 2.安装lnmp: wget http://soft.vpser.net/lnmp/lnmp1.5.tar.gz -cO ln ...