LruCache算法原理及实现
LruCache算法原理及实现
LruCache算法原理
LRU为Least Recently Used的缩写,意思也就是近期最少使用算法。LruCache将LinkedHashMap的顺序设置为LRU顺序来实现LRU缓存,每次调用get并获取到值(也就是从内存缓存中命中),则将该对象移到链表的尾端。调用put插入新的对象也是存储在链表尾端,这样当内存缓存达到设定的最大值时,将链表头部的对象(近期最少用到的)移除。
基于LinkedHashMap的LRUCache的实现,关键是重写LinkedHashMap的removeEldestEntry方法,在LinkedHashMap中该方法默认返回false(LRUCache本身未考虑线程安全的问题),这样此映射的行为将类似于正常映射,即永远不能移除最旧的元素。
LruCache算法实现的思路
- 按从近期访问最少到近期访问最多的顺序(即访问顺序)来保存元素,LinkedHashMap提供了LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder)构造函数,该哈希映射的迭代顺序就是最后访问其条目的顺序,这种映射很适合构建LRU缓存。
- LinkedHashMap提供了removeEldestEntry(Map.Entry<K,V> eldest)方法。该方法在每次添加新条目时移除最旧条目,但该方法默认返回false,这样,此映射的行为将类似于正常映射,即永远不能移除最旧的元素。因而需要重写该方法。
基于LinkedHashMap的LruCache具体实现
import java.util.LinkedHashMap;
import java.util.Map;
public class LruCache<K, V> {
private LinkedHashMap<K, V> map;//链表存储对象
private int cacheSize;//cache大小
private int hitCount;//命中次数
private int missCount;//未命中次数
public synchronized final int getCacheSize() {
return cacheSize;
}
public synchronized final int getHitCount() {
return hitCount;
}
public synchronized final int getMissCount() {
return missCount;
}
static final int DEFAULT_CACHE_SIZE = 2;//cache默认大小
public V put(K key, V value) {
return map.put(key, value);
}
public V get(Object key) {
if (null == key) {
throw new NullPointerException(" key == null ");
}
V val = null;
synchronized (this) {
val = map.get(key);
if (null != val) {
hitCount += 1;
return val;
}
missCount += 1;
}
return val;
}
public LruCache() {
this(DEFAULT_CACHE_SIZE);
}
public LruCache(int cacheSize) {
this.cacheSize = cacheSize;
int hashTableSize = (int) (Math.ceil(cacheSize / 0.75f) + 1);
//LruCache算法实现的关键
//1、按从近期访问最少到近期访问最多的顺序(即访问顺序)来保存元素,那么请使用下面的构造方法构造LinkedHashMap
//public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder); //该哈希映射的迭代顺序就是最后访问其条目的顺序,这种映射很适合构建LRU缓存。
//2、LinkedHashMap提供了removeEldestEntry(Map.Entry<K,V> eldest)方法。该方法可以提供在每次添加新条目时移除最旧条目的实现程序,默认返回false,这样,此映射的行为将类似于正常映射,即永远不能移除最旧的元素。
map = new LinkedHashMap<K, V>(hashTableSize, 0.75f, true){
private static final long serialVersionUID = 1L;
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
System.out.println(" ***** size=" + size() + " cacheSize=" + LruCache.this.cacheSize + " ****");
// return super.removeEldestEntry(eldest);
return size() > LruCache.this.cacheSize;
}
};
}
public static void main(String[] args) {
LruCache<String, String> lruCache = new LruCache<String, String>(3);
lruCache.put("1", "1");
lruCache.put("2", "2");
lruCache.put("3", "3");
lruCache.put("4", "4");
lruCache.put("5", "5");
System.out.println("==========================================================================");
System.out.println("hitCount=" + lruCache.getHitCount() + " missCount=" + lruCache.getMissCount());
System.out.println("==========================================================================");
System.out.println(lruCache.get("1") + " hitCount=" + lruCache.getHitCount() + " missCount=" + lruCache.getMissCount());
System.out.println(lruCache.get("2") + " hitCount=" + lruCache.getHitCount() + " missCount=" + lruCache.getMissCount());
System.out.println(lruCache.get("3") + " hitCount=" + lruCache.getHitCount() + " missCount=" + lruCache.getMissCount());
System.out.println(lruCache.get("4") + " hitCount=" + lruCache.getHitCount() + " missCount=" + lruCache.getMissCount());
System.out.println(lruCache.get("4") + " hitCount=" + lruCache.getHitCount() + " missCount=" + lruCache.getMissCount());
System.out.println(lruCache.get("4") + " hitCount=" + lruCache.getHitCount() + " missCount=" + lruCache.getMissCount());
System.out.println(lruCache.get("4") + " hitCount=" + lruCache.getHitCount() + " missCount=" + lruCache.getMissCount());
lruCache.put("6", "6");
lruCache.put("7", "7");
System.out.println(lruCache.get("4") + " hitCount=" + lruCache.getHitCount() + " missCount=" + lruCache.getMissCount());
lruCache.put("8", "8");
System.out.println(lruCache.get("5") + " hitCount=" + lruCache.getHitCount() + " missCount=" + lruCache.getMissCount());
System.out.println("==========================================================================");
for(Map.Entry<String, String> entry : lruCache.map.entrySet()) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}
执行结果
***** size=1 cacheSize=3 ****
***** size=2 cacheSize=3 ****
***** size=3 cacheSize=3 ****
***** size=4 cacheSize=3 ****
***** size=4 cacheSize=3 ****
==========================================================================
hitCount=0 missCount=0
==========================================================================
null hitCount=0 missCount=1
null hitCount=0 missCount=2
3 hitCount=1 missCount=2
4 hitCount=2 missCount=2
4 hitCount=3 missCount=2
4 hitCount=4 missCount=2
4 hitCount=5 missCount=2
***** size=4 cacheSize=3 ****
***** size=4 cacheSize=3 ****
4 hitCount=6 missCount=2
***** size=4 cacheSize=3 ****
null hitCount=6 missCount=3
==========================================================================
7:7
4:4
8:8
参考文档:
LruCache算法原理及实现的更多相关文章
- Bagging与随机森林算法原理小结
在集成学习原理小结中,我们讲到了集成学习有两个流派,一个是boosting派系,它的特点是各个弱学习器之间有依赖关系.另一种是bagging流派,它的特点是各个弱学习器之间没有依赖关系,可以并行拟合. ...
- RSA算法原理
一直以来对linux中的ssh认证.SSL.TLS这些安全认证似懂非懂的.看到阮一峰博客中对RSA算法的原理做了非常详细的解释,看完之后茅塞顿开,关于RSA的相关文章如下 RSA算法原理(一) RSA ...
- MySQL索引背后的数据结构及算法原理【转】
本文来自:张洋的MySQL索引背后的数据结构及算法原理 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持 ...
- OpenGL学习进程(13)第十课:基本图形的底层实现及算法原理
本节介绍OpenGL中绘制直线.圆.椭圆,多边形的算法原理. (1)绘制任意方向(任意斜率)的直线: 1)中点画线法: 中点画线法的算法原理不做介绍,但这里用到最基本的画0<=k ...
- 支持向量机原理(四)SMO算法原理
支持向量机原理(一) 线性支持向量机 支持向量机原理(二) 线性支持向量机的软间隔最大化模型 支持向量机原理(三)线性不可分支持向量机与核函数 支持向量机原理(四)SMO算法原理 支持向量机原理(五) ...
- 分布式缓存技术memcached学习(四)—— 一致性hash算法原理
分布式一致性hash算法简介 当你看到“分布式一致性hash算法”这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么.在分析分布式一致性hash算法原理之前,我们先来了解一下这几 ...
- Logistic回归分类算法原理分析与代码实现
前言 本文将介绍机器学习分类算法中的Logistic回归分类算法并给出伪代码,Python代码实现. (说明:从本文开始,将接触到最优化算法相关的学习.旨在将这些最优化的算法用于训练出一个非线性的函数 ...
- GBDT算法原理深入解析
GBDT算法原理深入解析 标签: 机器学习 集成学习 GBM GBDT XGBoost 梯度提升(Gradient boosting)是一种用于回归.分类和排序任务的机器学习技术,属于Boosting ...
- Atitit 图像清晰度 模糊度 检测 识别 评价算法 原理
Atitit 图像清晰度 模糊度 检测 识别 评价算法 原理 1.1. 图像边缘一般都是通过对图像进行梯度运算来实现的1 1.2. Remark: 1 1.3. 1.失焦检测. 衡量画面模糊的主要方 ...
随机推荐
- 篇二:JSON解析
前台以json形式的数据格式传到后台,代码如下: import net.sf.json.JSONObject; public class JsonUtility { /** * 解析JSON 对象为对 ...
- JS:window.onload的使用
1.最简单的调用方式 直接写到html的body标签里面,如: (html) (body onload="func()") (/body) (/html) 2.在JS语句调用 (s ...
- linux下查看最消耗CPU、内存的进程
2012-11-19 15:38:04 分类: LINUX 1.CPU占用最多的前10个进程: ps auxw|head -1;ps auxw|sort -rn -k3|head -10 2.内存消耗 ...
- 关于闭包(closure)的一些概念
和其他大多数现代编程语言一样,JS也采用词法作用域,也就是说,函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的.为了实现这种词法作用域,JS函数对象的内部状态不仅包含 ...
- django models进行数据库增删查改
在cmd 上运行 python manage.py shell 引入models的定义 from app.models import myclass ##先打这一行 ------这些是 ...
- 基于Dubbo框架构建分布式服务(二)
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> ...
- 基于Dubbo框架构建分布式服务(一)
Dubbo是Alibaba开源的分布式服务框架,我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务应用场景来选择合适的集群容错模式,这个对于很多应用都是迫切希望的,只需要通过简单的配 ...
- ijkplayer demo效果图
如下截图所示,用https://github.com/Bilibili/ijkplayer.git源码编译生成的ijkplayer app效果图,是这样的吗?有没有朋友指点下?
- SQL Server存储过程创建和修改
create proc Get_Data( @Del_ID varchar(36))asselect * from Depts where DeptId=@Del_ID select * from D ...
- iOS之UIKit系列教程<一>
前言:博主接触iOS的编程也有一段时间,今天把有关UI控件的一些知识在这里做一些总结. 申明:此系列文章都是使用目前最新版本swift3.0.1进行讲解的,与其他版本可能略有差异. 一,UIKit之设 ...