<K, V>型缓存:LRU策略 FIFO策略
<K, V>型缓存:LRU策略 FIFO策略
这两种替换策略都是通过 LinkedHashMap 实现
LinkedHashMap:
LinkedHashMap 继承自 HashMap,所以它的底层仍然是基于拉链式散列结构。该结构由数组和链表+红黑树,在此基础上LinkedHashMap 增加了一条双向链表,保持遍历顺序和插入顺序一致的问题。
访问顺序存储的LinkedHashMap会把get方法对应的Entry节点放置在Entry链表表尾。LinkedHashMap构造函数有3个参数:
public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder),其中:
initialCapacity:是初始数组长度
loadFactor:负载因子,表示数组的元素数量/数组长度超过这个比例,数组就要扩容
accessOrder:false: 基于插入顺序(默认) true: 基于访问顺序
当accessOrder为true,每次get元素的时候,都会去执行 afterNodeAccess 方法,这个方法会将元素重新插入到双向链表的结尾。
LinkedHashMap在HashMap的基础上使用一个双端链表维持有序的节点。这个有序并不是通常意义上的大小关系,默认情况下使用的插入顺序,意味着新插入的节点被添加到双端链表的尾部,而一旦使用了访问顺序,即accessOrder为true,那么在访问某一节点时,会将该节点移到双端链表的尾部。正因为此特性,可以在LinkedHashMap中使用三个参数的构造方法并制定accessOrder为true将LinkedHashMap实现为LRU缓存,这样经常访问的就会被移到链表的尾部,而越少访问的就在链表的头部。
由于双端链表维持了所有的节点,所以keySet()、values()以及entrySet()得到的键、值、键值对都是按照双端链表中的节点顺序的。
另外尤其需要注意的是,在put、get、remove方法中涉及到的双端链表的操作,由于都是引用的更改,所以并没有影响到HashMap的底层结构:数组+链表+红黑树。
LRU Cache:
LRU Cache 通过重写 removeEldestEntry() 方法实现元素替换,同时 accessOrder 参数设置为 true,表示使用访问顺序
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
public class FIFOCache<K, V> {
private final int MAX_CACHE_SIZE;
private final float DEFAULT_LOAD_FACTORY = 0.75f;
LinkedHashMap<K, V> map;
public FIFOCache(int cacheSize) {
MAX_CACHE_SIZE = cacheSize;
int capacity = (int)Math.ceil(MAX_CACHE_SIZE / DEFAULT_LOAD_FACTORY) + 1;
/*
* 第三个参数设置为true,代表linkedlist按访问顺序排序,可作为LRU缓存
* 第三个参数设置为false,代表按插入顺序排序,可作为FIFO缓存
*/
map = new LinkedHashMap<K, V>(capacity, DEFAULT_LOAD_FACTORY, false) {
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> 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();
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
for (Map.Entry<K, V> entry : map.entrySet()) {
stringBuilder.append(String.format("%s: %s ", entry.getKey(), entry.getValue()));
}
return stringBuilder.toString();
}
}
FIFO Cache:
accessOrder 参数设置为 false,表示使用插入顺序
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
public class FIFOCache<K, V> {
private final int MAX_CACHE_SIZE;
private final float DEFAULT_LOAD_FACTORY = 0.75f;
LinkedHashMap<K, V> map;
public FIFOCache(int cacheSize) {
MAX_CACHE_SIZE = cacheSize;
int capacity = (int)Math.ceil(MAX_CACHE_SIZE / DEFAULT_LOAD_FACTORY) + 1;
/*
* 第三个参数设置为true,代表linkedlist按访问顺序排序,可作为LRU缓存
* 第三个参数设置为false,代表按插入顺序排序,可作为FIFO缓存
*/
map = new LinkedHashMap<K, V>(capacity, DEFAULT_LOAD_FACTORY, false) {
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> 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();
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
for (Map.Entry<K, V> entry : map.entrySet()) {
stringBuilder.append(String.format("%s: %s ", entry.getKey(), entry.getValue()));
}
return stringBuilder.toString();
}
}
<K, V>型缓存:LRU策略 FIFO策略的更多相关文章
- 缓存算法(FIFO 、LRU、LFU三种算法的区别)
FIFO算法 FIFO 算法是一种比较容易实现的算法.它的思想是先进先出(FIFO,队列),这是最简单.最公平的一种思想,即如果一个数据是最先进入的,那么可以认为在将来它被访问的可能性很小.空间满的时 ...
- Java实现缓存(LRU,FIFO)
现在软件或者网页的并发量越来越大了,大量请求直接操作数据库会对数据库造成很大的压力,处理大量连接和请求就会需要很长时间,但是实际中百分之80的数据是很少更改的,这样就可以引入缓存来进行读取,减少数据库 ...
- 算法之如何实现LRU缓冲淘汰策略
1)什么是缓存? 缓存是一种提高数据读取性能的技术,在硬件设计.软件开发中都有着非广泛的应用,比如常见的CPU缓存.数据库缓存.浏览器缓存等等. 2)为什么使用缓存?即缓存的特点缓存的大小是有限的,当 ...
- 每天一点点之数据结构与算法 - 应用 - 分别用链表和数组实现LRU缓冲淘汰策略
一.基本概念: 1.什么是缓存? 缓存是一种提高数据读取性能的技术,在硬件设计.软件开发中都有着非广泛的应用,比如常见的CPU缓存.数据库缓存.浏览器缓存等等. 2.为什么使用缓存?即缓存的特点缓 ...
- 昨天面试被问到的 缓存淘汰算法FIFO、LRU、LFU及Java实现
缓存淘汰算法 在高并发.高性能的质量要求不断提高时,我们首先会想到的就是利用缓存予以应对. 第一次请求时把计算好的结果存放在缓存中,下次遇到同样的请求时,把之前保存在缓存中的数据直接拿来使用. 但是, ...
- 使用Go实现健壮的内存型缓存
使用Go实现健壮的内存型缓存 本文介绍了缓存的常见使用场景.选型以及注意点,比较有价值. 译自:Implementing robust in-memory cache with Go 内存型缓存是一种 ...
- 关于时间序列数据库的思考——(1)运用hash文件(例如:RRD,Whisper) (2)运用LSM树来备份(例如:LevelDB,RocksDB,Cassandra) (3)运用B-树排序和k/v存储(例如:BoltDB,LMDB)
转自:http://0351slc.com/portal.php?mod=view&aid=12 近期网络上呈现了有关catena.benchmarking boltdb等时刻序列存储办法的介 ...
- java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)
java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...
- C#泛型集合之Dictionary<k, v>使用技巧
1.要使用Dictionary集合,需要导入C#泛型命名空间 System.Collections.Generic(程序集:mscorlib) 2.描述 1).从一组键(Key)到一组值(Value) ...
- C#泛型集合—Dictionary<K,V>使用技巧
转载:http://blog.csdn.net/a125138/article/details/7742022 1.要使用Dictionary集合,需要导入C#泛型命名空间 System.Collec ...
随机推荐
- 杭电OJ1029题C++实现
解题思路:因为要求的数出现的次数总是比其他数字出现的次数多1,所以若总是用相同的数去与其他的数相抵,那么最后只剩下一个,那就是要求的数. 另外需要注意的一点就是,最好不要去开长度为999999的数组, ...
- 解决:pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it‘s not in your PATH. See README file for more information.
问题:使用pytesseract库识别图片中文字时出现报错 代码: import pytesseract from PIL import Image,ImageEnhance img=Image.op ...
- 【摘】python和它的内置类型子类化
python和它的内置类型子类化 看个好玩的东西 class Folder(list): def __init__(self, name): self.name = name def dir(self ...
- 爱心代码_HTML
直接上效果 <!doctype html> <html> <head> <meta charset="utf-8"> <tit ...
- 洛谷P1203 坏掉的项链
洛谷P1203 坏掉的项链 首先看到这题的数据样例,3<=n<=350,不是水水暴搜就过了嘛 不难想到暴力解,先破环成链 因为可能有全部都可换成一种颜色的情况,考虑每次遇到s[i]==s[ ...
- vue+element 表格动态列添加点击事件与排序(/或者空值排最后)
<template> <div> <el-table ref="tableData" :data="tableData& ...
- C语言初级阶段5——函数2
C语言初级阶段5--函数2 址传递 1.地址:在定义变量,数组,函数等等,系统会自动给分配他们的内存区域(地址),把这个数据放到这个地址上面. 2.&:&a 得到a的地址编号 3.*: ...
- Vue3 向window注入方法 TS警告 元素隐式具有 "any" 类型,因为索引表达式的类型不为 "number" 问题解决。
window['funcName'] = function(){}; // 'funcName'会标红警告 (window as any).funcName = function(){}; // 正确 ...
- EXT GridPanel button 按钮 事件 方法 DirectMethod
C# 代码 //首页 Ext.Net.Button btnFirst = new Ext.Net.Button(); btnFirst.Icon = Icon.ControlStartBlue; bt ...
- 中国移动光猫(吉比特h2-3S)超级用户名与密码
超级用户名 CMCCAdmin 密码 aDm8H%MdA