缓存接口定义

/**
* 缓存接口
*
* @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. 关于“关于C#装箱的疑问”帖子的个人看法 (原发布csdn 2017年10月07日 10:21:10)

    前言 昨天晚上闲着无事,就上csdn逛了一下,突然发现一个帖子很有意思,就点进去看了一下. 问题很精辟 int a = 1; object b=a; object c = b; c = 2; 为什么b ...

  2. C#安全类型转换基于convert

    using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Globalization; n ...

  3. Golang fmt Printf 格式化参数手册/详解/说明

    fmt 包实现了格式化I/O函数,类似于C的 printf 和 scanf. 格式“占位符”衍生自C,但比C更简单. fmt 包的官方文档对Printing和Scanning有很详细的说明.这里就直接 ...

  4. Bootstrap3-导航条

    1. 定义导航条 <!-- 导航条 navbar --> <div class="navbar nav-bar-default"> <ul class ...

  5. 2019-09-16 curl简单操作

    1.get请求 (使用file_get_contents()函数也可以实现get请求) //http_build_query() 构造一个url字符串 function http_get($url) ...

  6. .net Redis分布式锁,Dictionary,ConcurrentDictionary 介绍

    1.背景 在计算机世界里,对于锁大家并不陌生,在现代所有的语言中几乎都提供了语言级别锁的实现,为什么我们的程序有时候会这么依赖锁呢?这个问题还是要从计算机的发展说起,随着计算机硬件的不断升级,多核cp ...

  7. windows10风格 springboot vue.js html 跨域 前后分离 activiti 整合项目框架源码

    官网:www.fhadmin.org 此项目为Springboot工作流版本 windows 风格,浏览器访问操作使用,非桌面应用程序. 1.代码生成器: [正反双向](单表.主表.明细表.树形表,快 ...

  8. ta和夏天一起来了

    目录 ta和夏天一起来了 上半年,过去的就让去过去,遗憾的也别再遗憾. 下半年,拥有的请好好珍惜,想要的请努力去追. ta和夏天一起来了 ​ 转眼结束了2019的上半年,在这个月末, 季度末, 周末, ...

  9. JavaScript的Proxy可以做哪些有意思的事儿

    摘要: 神奇而有趣的Proxy. 原文:拿Proxy可以做哪些有意思的事儿 作者:贾顺名 Fundebug经授权转载,版权归原作者所有. Proxy是什么 首先,我们要清楚,Proxy是什么意思,这个 ...

  10. 树莓派初入门(1):SSH远程登录与VNC远程桌面

    前言: 本文主要讲解,对于一个无树莓派显示屏,无键盘,无鼠标,手边只有手机,电脑和一个已烧录好raspbian-stretch系统的树莓派3B+的玩家,如何进行远程登录,进而可以进程桌面的连接. 工具 ...