LRU经典算法的原理与实现
LRU least recently used.顾名思义,是根据数据的活跃度进行更新的缓存算法。
LRU Cache的LinkedHashMap实现:
LinkedHashMap自身已经实现了顺序存储,默认情况下是按照元素的添加顺序存储,也可以启用按照访问顺序存储,即最近读取的数据放在最前面,最早读取的数据放在最后面,然后它还有一个判断是否删除最老数据的方法,默认是返回false,即不删除数据,我们使用LinkedHashMap实现LRU缓存的方法就是对LinkedHashMap实现简单的扩展,扩展方式有两种,一种是inheritance,一种是delegation,具体使用什么方式看个人喜好
//LinkedHashMap的一个构造函数,当参数accessOrder为true时,即会按照访问顺序排序,最近访问的放在最前,最早访问的放在后面
public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
} //LinkedHashMap自带的判断是否删除最老的元素方法,默认返回false,即不删除老数据
//我们要做的就是重写这个方法,当满足一定条件时删除老数据
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
采用inheritance方式实现比较简单,而且实现了Map接口,在多线程环境使用时可以使用 Collections.synchronizedMap()方法实现线程安全操作
package cn.lzrabbit.structure.lru; import java.util.LinkedHashMap;
import java.util.Map; /**
* Created by liuzhao on 14-5-15.
*/
public class LRUCache2<K, V> extends LinkedHashMap<K, V> {
private final int MAX_CACHE_SIZE; public LRUCache2(int cacheSize) {
super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);
MAX_CACHE_SIZE = cacheSize;
} @Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > MAX_CACHE_SIZE;
} @Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (Map.Entry<K, V> entry : entrySet()) {
sb.append(String.format("%s:%s ", entry.getKey(), entry.getValue()));
}
return sb.toString();
}
}
这样算是比较标准的实现吧,实际使用中这样写还是有些繁琐,更实用的方法时像下面这样写,省去了单独见一个类的麻烦
final int cacheSize = 100;
Map<String, String> map = new LinkedHashMap<String, String>((int) Math.ceil(cacheSize / 0.75f) + 1, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
return size() > cacheSize;
}
};
LRU缓存LinkedHashMap(delegation)实现
delegation方式实现更加优雅一些,但是由于没有实现Map接口,所以线程同步就需要自己搞定了
package cn.lzrabbit.structure.lru; import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set; /**
* Created by liuzhao on 14-5-13.
*/
public class LRUCache3<K, V> { private final int MAX_CACHE_SIZE;
private final float DEFAULT_LOAD_FACTOR = 0.75f;
LinkedHashMap<K, V> map; public LRUCache3(int cacheSize) {
MAX_CACHE_SIZE = cacheSize;
//根据cacheSize和加载因子计算hashmap的capactiy,+1确保当达到cacheSize上限时不会触发hashmap的扩容,
int capacity = (int) Math.ceil(MAX_CACHE_SIZE / DEFAULT_LOAD_FACTOR) + 1;
map = new LinkedHashMap(capacity, DEFAULT_LOAD_FACTOR, true) {
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > MAX_CACHE_SIZE;
}
};
} public synchronized void put(K key, V value) {
map.put(key, value);
} public synchronized V get(K key) {
return map.get(key);
} public synchronized void remove(K key) {
map.remove(key);
} public synchronized Set<Map.Entry<K, V>> getAll() {
return map.entrySet();
} public synchronized int size() {
return map.size();
} public synchronized void clear() {
map.clear();
} @Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (Map.Entry entry : map.entrySet()) {
sb.append(String.format("%s:%s ", entry.getKey(), entry.getValue()));
}
return sb.toString();
}
}
注:此实现为非线程安全,若在多线程环境下使用需要在相关方法上添加synchronized以实现线程安全操作
LRU经典算法的原理与实现的更多相关文章
- Java中的经典算法之冒泡排序(Bubble Sort)
Java中的经典算法之冒泡排序(Bubble Sort) 神话丿小王子的博客主页 原理:比较两个相邻的元素,将值大的元素交换至右端. 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面.即在第一 ...
- Java中的经典算法之选择排序(SelectionSort)
Java中的经典算法之选择排序(SelectionSort) 神话丿小王子的博客主页 a) 原理:每一趟从待排序的记录中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕.也就是:每一趟 ...
- JS的十大经典算法排序
引子 有句话怎么说来着: 雷锋推倒雷峰塔,Java implements JavaScript. 当年,想凭借抱Java大腿火一把而不惜把自己名字给改了的JavaScript(原名LiveScript ...
- mahout中kmeans算法和Canopy算法实现原理
本文讲一下mahout中kmeans算法和Canopy算法实现原理. 一. Kmeans是一个很经典的聚类算法,我想大家都非常熟悉.虽然算法较为简单,在实际应用中却可以有不错的效果:其算法原理也决定了 ...
- 机器学习经典算法详解及Python实现--基于SMO的SVM分类器
原文:http://blog.csdn.net/suipingsp/article/details/41645779 支持向量机基本上是最好的有监督学习算法,因其英文名为support vector ...
- 经典算法题每日演练——第八题 AC自动机
原文:经典算法题每日演练--第八题 AC自动机 上一篇我们说了单模式匹配算法KMP,现在我们有需求了,我要检查一篇文章中是否有某些敏感词,这其实就是多模式匹配的问题. 当然你也可以用KMP算法求出,那 ...
- 非对称加密技术- RSA算法数学原理分析
非对称加密技术,在现在网络中,有非常广泛应用.加密技术更是数字货币的基础. 所谓非对称,就是指该算法需要一对密钥,使用其中一个(公钥)加密,则需要用另一个(私钥)才能解密. 但是对于其原理大部分同学应 ...
- PageRank算法--从原理到实现
本文将介绍PageRank算法的相关内容,具体如下: 1.算法来源 2.算法原理 3.算法证明 4.PR值计算方法 4.1 幂迭代法 4.2 特征值法 4.3 代数法 5.算法实现 5.1 基于迭代法 ...
- K-means算法的原理、优缺点及改进(转)
文章内容转载自:http://blog.csdn.net/sinat_35512245/article/details/55051306 ...
随机推荐
- 配置taglib的uri的2种方法
推荐方法1 1.把uri写在tld文件中,tld放在WEB-INF文件夹下,例如: <short-name>就对应了你在jsp中引用的时候<%@ taglib prefix=&quo ...
- jQuery 实战读书笔记之第三章:操作 jQuery 集合
创建新 HTML 元素 $('<div>Hello</div>'); /* 创建等价的空 div 元素 */ $('<div>'); $('<div /> ...
- [转]Python定时任务框架APScheduler
APScheduler是基于Quartz的 一个Python定时任务框架,实现了Quartz的所有功能,使用起来十分方便.提供了基于日期.固定时间间隔以及crontab类型的任务,并且可以 持久化任务 ...
- Intellij IDEA常用快捷键整理
ps:使用Intellij IDEA编辑器有蛮长一段时间了.哈哈.整合一下常用的快捷.避免自己以后还要再找. 顺序大概就是从上到下的 Alt + ENTER : 自动修正,提示Alt + Insert ...
- web.py使用要点
这几天有一个构建restful services的需求,我采用了web.py,之前并没有使用过,但在使用中确实给我带来了很多惊喜.当然,最大的惊喜就是简单,方便.之前开发restful服务的时候,采用 ...
- Linux进程状态转换图
Linux进程状态 Linux内核中的进程状态 ◆运行状态(TASK_RUNNING) 指正在被CPU运行或者就绪的状态.这样的进程被成为runnning进程.运行态的进程可以分为3种情况:内核运行态 ...
- ios-A+B经典问题
// // main.m // a+b // #import <Foundation/Foundation.h> #import "Calcultor.h" int m ...
- linux怎么发邮件
邮箱配置: tail /etc/mail.rc #要写在一行 set from=gb17735517416@163.com smtp=smtp.163.com smtp-auth-user=gb ...
- jsp页面form表单提交时候乱码
1.问题描述: 表单提交中文乱码问题,怎么解决 2.原因 当表单传输到服务器上时,服务器会将传输的数据进行编码(iso-8859-1),然后当我们从服务器上面取数据的时候,就会出现乱码 3.解决的方式 ...
- linux less使用方法
less 工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大.less 的用法比起 more 更加的有弹性.在 more 的时候,我们并没有办法向前面翻 ...