缓存接口定义

/**
* 缓存接口
*
* @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缓存简单实现的更多相关文章

  1. LRU缓存实现(Java)

    LRU Cache的LinkedHashMap实现 LRU Cache的链表+HashMap实现 LinkedHashMap的FIFO实现 调用示例 LRU是Least Recently Used 的 ...

  2. 面试挂在了 LRU 缓存算法设计上

    好吧,有人可能觉得我标题党了,但我想告诉你们的是,前阵子面试确实挂在了 RLU 缓存算法的设计上了.当时做题的时候,自己想的太多了,感觉设计一个 LRU(Least recently used) 缓存 ...

  3. Java集合详解5:深入理解LinkedHashMap和LRU缓存

    今天我们来深入探索一下LinkedHashMap的底层原理,并且使用linkedhashmap来实现LRU缓存. 摘要: HashMap和双向链表合二为一即是LinkedHashMap.所谓Linke ...

  4. 04 | 链表(上):如何实现LRU缓存淘汰算法?

    今天我们来聊聊“链表(Linked list)”这个数据结构.学习链表有什么用呢?为了回答这个问题,我们先来讨论一个经典的链表应用场景,那就是+LRU+缓存淘汰算法. 缓存是一种提高数据读取性能的技术 ...

  5. LRU缓存原理

    LRU(Least Recently Used)  LRU是近期最少使用的算法,它的核心思想是当缓存满时,会优先淘汰那些近期最少使用的缓存对象. 采用LRU算法的缓存有两种:LrhCache和DisL ...

  6. 链表(上):如何实现LRU缓存淘汰算法?

    一.什么是链表 和数组一样,链表也是一种线性表. 从内存结构来看,链表的内存结构是不连续的内存空间,是将一组零散的内存块串联起来,从而进行数据存储的数据结构. 链表中的每一个内存块被称为节点Node. ...

  7. [转]LRU缓存实现(Java)

    LRU Cache的LinkedHashMap实现 LRU Cache的链表+HashMap实现 LinkedHashMap的FIFO实现 调用示例 LRU是Least Recently Used 的 ...

  8. 请用Java设计一个Least Recently Used (LRU) 缓存

    LRU介绍:LRU是Least Recently Used的缩写,即最少使用页面置换算法,是为虚拟页式存储管理服务的, 思路介绍: 能够使用两个标准的数据结构来实现.Map和Queue.由于须要支持多 ...

  9. 链表:如何实现LRU缓存淘汰算法?

    缓存淘汰策略: FIFO:先入先出策略 LFU:最少使用策略 LRU:最近最少使用策略   链表的数据结构: 可以看到,数组需要连续的内存空间,当内存空间充足但不连续时,也会申请失败触发GC,链表则可 ...

随机推荐

  1. Quartz.Net 删除一个Job

    Quartz.Net 删除Job 来博客园的第一篇文章先写个简单的,希望能帮助到大家. 步入正题: Quartz.Net有三个重要的概念,分别是 Scheduler .Job .Trigger.  S ...

  2. 关于Panel隐藏横向滚动条

    不设置控件的AutoScroll属性,在后台写代码,就可以隐藏掉横向滚动条

  3. Python基础12

    jupyter notebook 快捷键 ”Ctrl + / ” 快速注释/撤销注释.注释整行或者整段代码.

  4. 解决 Electron 5.0 版本出现 require is not defined 的问题

    Electron已经发布了5.0正式版,升级后发现原来能运行的代码报错提示require is not defined 经查相关资料,原来官方在5.0版本修改了nodeIntegration的默认值, ...

  5. EF自动创建数据库步骤之二(继承DbContext类)

    创建好表实体类后,接着就是创建数据库上下文(继承DbContext)并将实体类添加进来. 代码示例如下: using DBClientEntity; using System; using Syste ...

  6. vue-quill-editor富文本编辑器 中文翻译组件,编辑与展示

    vue项目中用到了富文本编辑器,网上找了一些,觉得vue-quill-editor最好用, ui简洁,功能也好配,够用了,文档不好读,有些小细节需要自己注意,我懒得分析,就封装成了组件 大家用的时候直 ...

  7. `Java`中`abstract class`与`interface`区别

    abstract class Java中允许使用abstract修饰符声明方法,此时只定义方法但是不实现方法(abstract修饰的方法没有主体,只有一个签名和一个分号). 以下是abstract方法 ...

  8. Linux shell case条件判断及位置变量

    case语句使用于需要进行多重分支的应用情况 case分支判断结构 语法: case 变量名称 in      value1)          statement          statemen ...

  9. SpringBoot 自定义线程池,多线程

    原文:https://www.jianshu.com/p/832f2b162450 我们都知道spring只是为我们简单的处理线程池,每次用到线程总会new 一个新的线程,效率不高,所以我们需要自定义 ...

  10. 京东js加密 nloginpwd 破解

    京东登录,有一个参数nloginpwd,是加密字段. 第一步:浏览器抓包 第二部:搜索加密字段 js 代码 第三部: 下断点 2. js代码: var navigator = {}; var wind ...