LRU Cache(Least Recent Used缓存)
时间:2019-01-11
本文章向大家介绍LRU Cache(Least Recent Used缓存),主要包括LRU Cache(Least Recent Used缓存)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
在有限内存空间中,抛弃距当前时间最远被使用(访问)的元素的缓存的数据结构,能够添加元素,读取元素。这个数据结构在操作系统中经常被使用到,见wikipedia链接https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)。
使用一个双端链表和一个HashMap可以在O(1)时间、O(n)空间内完成插入和查询操作。
双端链表数据结构定义如下:
private class DLinkedListNode<Key,Value>
{
Key key;
Value val;
DLinkedListNode pre;
DLinkedListNode next;
public DLinkedListNode(Key key,Value val)
{
this.key=key;
this.val=val;
this.pre=null;
this.next=null;
}
}
LRU Cache数据结构定义如下:
public class LRUCache<Key,Value> {
private HashMap<Key,DLinkedListNode> hashmap;
private int capacity; //缓存容量
private DLinkedListNode head; //双端链表头结点
private DLinkedListNode tail; //双端链表尾节点
public LRUCache(int capacity)
{
this.hashmap=new HashMap<>();
this.capacity=capacity;
this.head=null;
this.tail=null;
}
}
很基础的链表操作,泛型编程的详细代码实现如下:
import java.util.HashMap;
public class LRUCache<Key,Value> {
private HashMap<Key,DLinkedListNode> hashmap;
private int capacity; //缓存容量
private DLinkedListNode head; //双端链表头结点
private DLinkedListNode tail; //双端链表尾节点
private class DLinkedListNode<Key,Value>
{
Key key;
Value val;
DLinkedListNode pre;
DLinkedListNode next;
public DLinkedListNode(Key key,Value val)
{
this.key=key;
this.val=val;
this.pre=null;
this.next=null;
}
}
public LRUCache(int capacity)
{
this.hashmap=new HashMap<>();
this.capacity=capacity;
this.head=null;
this.tail=null;
}
public Value get(Key key)
{
DLinkedListNode node= hashmap.get(key);
if(node==null) //当hashmap中不存在这个key时,返回null
return null;
if(node!=this.tail) //存在这个key时,检查是否是尾节点:如果是尾节点,则该节点位置不动;如果不是尾节点,则需要移动位置。
{
if(node==this.head) //如果是头结点,则将头结点放在双端链表尾部
head=head.next;
else //如果不是头节点,则将该节点从双端链表中移到尾部
{
node.pre.next=node.next;
node.next.pre=node.pre;
}
tail.next=node;
node.pre=tail;
node.next=null;
tail=node;
}
return (Value)node.val;
}
public void put(Key key, Value value)
{
DLinkedListNode node=hashmap.get(key);
if(node!=null)
{
if(node==this.head)
{
head=head.next;
}
else
{
node.pre.next=node.next;
node.next.pre=node.pre;
}
tail.next=node;
node.pre=tail;
node.next=null;
tail=node;
}
else
{
DLinkedListNode newNode=new DLinkedListNode(key,value);
if(this.size()==this.capacity)
{
DLinkedListNode tmp=this.head;
this.head=this.head.next;
this.hashmap.remove(tmp.key);
}
if(head==null && tail==null)
{
this.head=newNode;
}
else
{
this.tail.next=newNode;
newNode.pre=this.tail;
newNode.next=null;
}
this.tail=newNode;
this.hashmap.put(key,newNode);
}
}
public int size()
{
return this.hashmap.size();
}
//单元测试
public static void main(String[] args)
{
LRUCache<Integer,String> lru=new LRUCache<>(4);
lru.put(1,"haha");
lru.put(2,"xixi");
lru.put(3,"hehe");
lru.put(2,"zeze");
lru.put(5,"xuxu");
lru.get(2);
lru.put(6,"enen");
}
}
- 使用GoogleAPI加载各种js框架
- Docker容器学习梳理--日常操作总结
- 马化腾:通向互联网未来的七个路标
- jQuery扩展以及gzip压缩测试
- python2.6升级到3.3.0 的操作记录
- 由javascript中"匿名函数调用写法"引出的一些东东
- javascript中定义私有方法(private method)
- python升级后带来的几个小问题
- 分布式监控系统Zabbix-3.0.3-完整安装记录(1)
- centos6.8下安装部署LNMP-(nginx1.8.0+php5.6.10+mysql5.6.12)
- IE7下当position:fixed遇到text-align:center
- 数组-在Shell脚本中的基本使用介绍
- .Net Core下通过Proxy 模式 使用 WCF
- javascript中function调用时的参数检测常用办法
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Java串口读卡器工具通信之RXTX
- 动态规划设计
- SpringBean 的实例化过程
- Android的Dialog弹出时隐藏导航栏效果,目前认为的最优解
- WebService接口调试如此简单
- 嵌入式linux下的c语言简易日志log模块,带颜色显示(一)
- 嵌入式linux下的c语言日志log模块,功能增强(二)
- Spring IOC源码最全分析
- 嵌入式linux之go语言开发(六)几行代码实现终端的远程日志诊断
- spring-mybatis 整合分析
- Spring 中循环依赖是如何解决?
- 走,HashMap,敢去爬山吗?
- Django+Vue开发生鲜电商平台之10.购物车、订单管理和支付功能
- 嵌入式linux之go语言开发(七)protobuf的使用
- 动手写简单的嵌入式操作系统一