LruCache算法原理及实现

LruCache算法原理

LRULeast Recently Used的缩写,意思也就是近期最少使用算法。LruCacheLinkedHashMap的顺序设置为LRU顺序来实现LRU缓存,每次调用get并获取到值(也就是从内存缓存中命中),则将该对象移到链表的尾端。调用put插入新的对象也是存储在链表尾端,这样当内存缓存达到设定的最大值时,将链表头部的对象(近期最少用到的)移除。

基于LinkedHashMapLRUCache的实现,关键是重写LinkedHashMapremoveEldestEntry方法,在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算法原理及实现的更多相关文章

  1. Bagging与随机森林算法原理小结

    在集成学习原理小结中,我们讲到了集成学习有两个流派,一个是boosting派系,它的特点是各个弱学习器之间有依赖关系.另一种是bagging流派,它的特点是各个弱学习器之间没有依赖关系,可以并行拟合. ...

  2. RSA算法原理

    一直以来对linux中的ssh认证.SSL.TLS这些安全认证似懂非懂的.看到阮一峰博客中对RSA算法的原理做了非常详细的解释,看完之后茅塞顿开,关于RSA的相关文章如下 RSA算法原理(一) RSA ...

  3. MySQL索引背后的数据结构及算法原理【转】

    本文来自:张洋的MySQL索引背后的数据结构及算法原理 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持 ...

  4. OpenGL学习进程(13)第十课:基本图形的底层实现及算法原理

        本节介绍OpenGL中绘制直线.圆.椭圆,多边形的算法原理.     (1)绘制任意方向(任意斜率)的直线: 1)中点画线法: 中点画线法的算法原理不做介绍,但这里用到最基本的画0<=k ...

  5. 支持向量机原理(四)SMO算法原理

    支持向量机原理(一) 线性支持向量机 支持向量机原理(二) 线性支持向量机的软间隔最大化模型 支持向量机原理(三)线性不可分支持向量机与核函数 支持向量机原理(四)SMO算法原理 支持向量机原理(五) ...

  6. 分布式缓存技术memcached学习(四)—— 一致性hash算法原理

    分布式一致性hash算法简介 当你看到“分布式一致性hash算法”这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么.在分析分布式一致性hash算法原理之前,我们先来了解一下这几 ...

  7. Logistic回归分类算法原理分析与代码实现

    前言 本文将介绍机器学习分类算法中的Logistic回归分类算法并给出伪代码,Python代码实现. (说明:从本文开始,将接触到最优化算法相关的学习.旨在将这些最优化的算法用于训练出一个非线性的函数 ...

  8. GBDT算法原理深入解析

    GBDT算法原理深入解析 标签: 机器学习 集成学习 GBM GBDT XGBoost 梯度提升(Gradient boosting)是一种用于回归.分类和排序任务的机器学习技术,属于Boosting ...

  9. Atitit 图像清晰度 模糊度 检测 识别 评价算法 原理

    Atitit 图像清晰度 模糊度 检测 识别 评价算法 原理 1.1. 图像边缘一般都是通过对图像进行梯度运算来实现的1 1.2. Remark: 1 1.3.  1.失焦检测. 衡量画面模糊的主要方 ...

随机推荐

  1. Nfs+Drdb+Heartbeat 数据存储高可用服务架构方案

    一.方案的应用场景 适用于2千万-3千万PV架构的网站,Nfs数据存储高可用服务方案 备注:互联网排名前30左右公司常用的架构 二.生产环境方案部署原理图 三.生产环境服务器硬件配置: 生产环境中采用 ...

  2. 常用的shell脚本

    [root@WEB1-live sh]# cat licai_fabu.sh #!/bin/bash pid=` ps -ef | grep java | grep '8011' | awk '{pr ...

  3. ABP 索引

    官方网站 Github ABP集合贴 @ kebinet https://www.codeproject.com/articles/1115763/using-asp-net-core-entity- ...

  4. PRINCE2特征(三)

    提到不确定性,可能很多从事项目管理相关工作的人都会感同身受,一系列临时性问题,比如:变更.延期.调整.计划赶不上变化.团队调整等的出现,都是项目中再正常不过的内容.但正常不等于合理,我们还是要去思考一 ...

  5. 分享一种容易理解的js去重排序方法

    <script> var arr=[1,8,6,4,88,22,99,4,6,86,5,58,89,5]; //先使用sort()函数去重 var a=arr.sort(function ...

  6. 小猪cms之怎样查询绑定的微网站模板

    微网站内容页面url g=Wap&m=Index&a=content (g=Wap)模块路径对应路径:\PigCms\Lib\Action\Wap (m=Index)控制文件对应文件: ...

  7. Git 耍不起来啊

    1.  $ git clone https://******.git Cloning into 'dt-engine-server'...fatal: unable to access 'https: ...

  8. 【poj3071】 Football

    http://poj.org/problem?id=3071 (题目链接) 题意 ${2^n}$个队伍打淘汰赛,输的被淘汰.第1个队打第2个队,第3个队打第4个队······给出第i个队伍打赢第j个队 ...

  9. Beta版本冲刺总汇

    DAY ONE: http://www.cnblogs.com/aruba/p/6149032.html posted @ 2016-12-09 12:37 DAY TWO: http://www.c ...

  10. Dictionary

    命名空间:System.Collections.Generic(程序集:mscorlib) Dictionary<TKey, TValue> 类   一般用法:通过key获取value,k ...