LRU缓存简单实现
缓存接口定义
/**
* 缓存接口
*
* @author zhi
*
*/
public interface ICache<K, V> {
/**
* 添加缓存数据
*
* @param key
* @param value
*/
void put(K key, V value); /**
* 获取缓存数据
*
* @param key
* @return
*/
V get(K key); /**
* 删除缓存数据
*
* @param key
* @return
*/
V remove(K key); /**
* 清除缓存
*/
void clear();
}
利用LinkedHashMap实现
import java.util.LinkedHashMap;
import java.util.Map; public class LRUCache<K, V> implements ICache<K, V> {
private Map<K, V> map = null; @SuppressWarnings("serial")
public LRUCache(final int maxCapacity) {
map = new LinkedHashMap<K, V>(maxCapacity, 0.75f, true) {
@Override
protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
return size() > maxCapacity;
}
};
} @Override
public V get(K key) {
return map.get(key);
} @Override
public synchronized void put(K key, V value) {
map.put(key, value);
} @Override
public V remove(K key) {
return map.remove(key);
} @Override
public void clear() {
map.clear();
}
}
利用双链表实现
import java.util.HashMap;
public class LRUCache<K, V> implements ICache<K, V> {
private final int maxCapacity;
private CacheItem first;
private CacheItem last;
private HashMap<K, CacheItem> cache;
public LRUCache(final int maxCapacity) {
this.maxCapacity = maxCapacity;
cache = new HashMap<K, CacheItem>(maxCapacity);
}
@Override
public V get(K key) {
CacheItem item = cache.get(key);
if (item == null) {
return null;
}
moveToFirst(item);
return item.value;
}
@Override
public synchronized void put(K key, V value) {
CacheItem item = cache.get(key);
if (item != null) {
item.value = value;
moveToFirst(item);
} else {
if (cache.size() == maxCapacity) {
cache.remove(last.key);
last = last.pre;
if (last == null) {
first = null;
} else {
last.next = null;
}
}
item = new CacheItem(key, value);
cache.put(key, item);
if (first != null) {
item.next = first;
first.pre = item;
}
first = item;
if (last == null) {
last = item;
}
}
}
@Override
public V remove(K key) {
if (cache.containsKey(key)) {
CacheItem item = cache.get(key);
if (item.pre != null) {
item.pre.next = item.next;
}
if (item.next != null) {
item.next.pre = item.pre;
}
if (item == first) {
first = item.next;
}
if (item == last) {
last = item.pre;
}
return cache.remove(key).value;
} else {
return null;
}
}
private void moveToFirst(CacheItem item) {
if (item == first) {
return;
}
if (item.next == null) {
last = item.pre;
}
item.pre.next = item.next;
item.next = first;
first = item;
first.pre = null;
}
@Override
public void clear() {
first = last = null;
cache.clear();
}
class CacheItem {
CacheItem pre;
CacheItem next;
K key;
V value;
public CacheItem(K key, V value) {
this.key = key;
this.value = value;
}
}
}
LRU缓存简单实现的更多相关文章
- LRU缓存实现(Java)
LRU Cache的LinkedHashMap实现 LRU Cache的链表+HashMap实现 LinkedHashMap的FIFO实现 调用示例 LRU是Least Recently Used 的 ...
- 面试挂在了 LRU 缓存算法设计上
好吧,有人可能觉得我标题党了,但我想告诉你们的是,前阵子面试确实挂在了 RLU 缓存算法的设计上了.当时做题的时候,自己想的太多了,感觉设计一个 LRU(Least recently used) 缓存 ...
- Java集合详解5:深入理解LinkedHashMap和LRU缓存
今天我们来深入探索一下LinkedHashMap的底层原理,并且使用linkedhashmap来实现LRU缓存. 摘要: HashMap和双向链表合二为一即是LinkedHashMap.所谓Linke ...
- 04 | 链表(上):如何实现LRU缓存淘汰算法?
今天我们来聊聊“链表(Linked list)”这个数据结构.学习链表有什么用呢?为了回答这个问题,我们先来讨论一个经典的链表应用场景,那就是+LRU+缓存淘汰算法. 缓存是一种提高数据读取性能的技术 ...
- LRU缓存原理
LRU(Least Recently Used) LRU是近期最少使用的算法,它的核心思想是当缓存满时,会优先淘汰那些近期最少使用的缓存对象. 采用LRU算法的缓存有两种:LrhCache和DisL ...
- 链表(上):如何实现LRU缓存淘汰算法?
一.什么是链表 和数组一样,链表也是一种线性表. 从内存结构来看,链表的内存结构是不连续的内存空间,是将一组零散的内存块串联起来,从而进行数据存储的数据结构. 链表中的每一个内存块被称为节点Node. ...
- [转]LRU缓存实现(Java)
LRU Cache的LinkedHashMap实现 LRU Cache的链表+HashMap实现 LinkedHashMap的FIFO实现 调用示例 LRU是Least Recently Used 的 ...
- 请用Java设计一个Least Recently Used (LRU) 缓存
LRU介绍:LRU是Least Recently Used的缩写,即最少使用页面置换算法,是为虚拟页式存储管理服务的, 思路介绍: 能够使用两个标准的数据结构来实现.Map和Queue.由于须要支持多 ...
- 链表:如何实现LRU缓存淘汰算法?
缓存淘汰策略: FIFO:先入先出策略 LFU:最少使用策略 LRU:最近最少使用策略 链表的数据结构: 可以看到,数组需要连续的内存空间,当内存空间充足但不连续时,也会申请失败触发GC,链表则可 ...
随机推荐
- Ubuntu Nginx https 配置
#配置http跳转到https 80跳转443server { listen ; server_name www.***.com www.***.cn; https://$server_name$re ...
- winform子窗口与父窗口的交互-使用委托与事件
实现子窗口与父窗口的交互,通过父窗口调用并控制子窗口,子窗口也能控制父窗口,使用委托和事件的方法,可以实现. 1.父窗口调用子窗口,并通过子窗口控制父窗口 新建工程,创建两个窗体 显示子窗体的代 ...
- 如何在windows 7 上使用docker
在window7上面本来是支持使用docker的, 但是我们可以通过安装docker toolbox来实现在windows7上使用docker. 参考网址: https://docs.docker.c ...
- 字节输出流FileOutputStream
#字节流 字节输出流FileOutputStream 创建输出流对象 OutputStream 流对象是一个抽象类,不能实例化.所以,我们要找一个具体的子类 :FileOutputStream. 查看 ...
- Java自学-集合框架 与数组的区别
Java集合框架与数组的区别 示例 1 : 使用数组的局限性 如果要存放多个对象,可以使用数组,但是数组有局限性 比如 声明长度是10的数组 不用的数组就浪费了 超过10的个数,又放不下 //Test ...
- git操作:删除仓库中的文件或目录
假定当前分支下,abc/123.txt需要从git仓库中删除: git .txt //删除abc目录下的123.txt文件,如果要删除abc目录,使用命令:git rm -r --cached abc ...
- Python开发环境的安装配置
要学习Python,我们首先要安装配置好Python的运行环境. 那么安装Python 2 还是 Python 3 呢? 当然是要选择Python 3 .这里来教大家安装稳定版Python3 的版本是 ...
- `Java`中`abstract class`与`interface`区别
abstract class Java中允许使用abstract修饰符声明方法,此时只定义方法但是不实现方法(abstract修饰的方法没有主体,只有一个签名和一个分号). 以下是abstract方法 ...
- 掌握 Async/Await
摘要: 还不用Async/Await就OUT了.. 原文:掌握 Async/Await 作者:Jartto Fundebug经授权转载,版权归原作者所有. 前端工程师肯定都经历过 JS 回调链狱的痛苦 ...
- FTP服务搭建配置笔记
1.什么是文件共享服务? 简单来说就是文件域存储块设备可以共享给他人使用. 1.1 实现文件共享服务的三种方式 FTP:属于应用层服务,可以跨平台使用 NFS:属于内核模式,不可以跨平台使用 Samb ...