10行Java代码实现最近被使用(LRU)缓存

在最近的面试中,我曾被多次问到,怎么实现一个最近最少使用(LRU)的缓存。缓存可以通过哈希表来实现,然而为这个缓存增加大小限制会变成另一个有意思的问题。现在我们看一下怎么实现。

最近最少使用缓存的回收

为了实现缓存回收,我们需要很容易做到:

  • 查询出最近最晚使用的项
  • 给最近使用的项做一个标记

链表可以实现这两个操作。检测最近最少使用的项只需要返回链表的尾部。标记一项为最近使用的项只需要从当前位置移除,然后将该项放置到头部。比较困难的事情是怎么快速的在链表中找到该项。

哈希表的帮助

看一下我们工具箱中的数据结构,哈希表可以在(消耗)常量的时间内索引到某个对象。如果我们创建一个形如key->链表节点的哈希表,我们就能够在常量时间内找到最近使用的节点。更甚的是,我们也能够在常量时间内判断节点的是否存在(或不存在);

找到这个节点后,我们就能将这个节点移动到链表的最前端,标记为最近使用的项了。

Java的捷径

据我所知,很少有一种编程语言的标准库中有通用的数据结构能提供上述功能的。这是一种混合的数据结构,我们需要在哈希表的基础上建立一个链表。但是
Java已经为我们提供了这种形式的数据结构-LinkedHashMap!它甚至提供可覆盖回收策略的方法(见removeEldestEntry文档)。唯一需要我们注意的事情是,改链表的顺序是插入的顺序,而不是访问的顺序。但是,有一个构造函数提供了一个选项,可以使用访问的顺序(见文档)。

无需多说:


  1. import java.util.LinkedHashMap; 
  2. import java.util.Map; 
  3.  
  4. public LRUCache<K, V> extends LinkedHashMap<K, V> { 
  5.   private int cacheSize; 
  6.  
  7.   public LRUCache(int cacheSize) { 
  8.     super(16, 0.75, true); 
  9.     this.cacheSize = cacheSize; 
  10.   } 
  11.  
  12.   protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { 
  13.     return size() >= cacheSize; 
  14.   } 

来源:51CTO

时间: 2024-10-30 14:39:20

10行Java代码实现最近被使用(LRU)缓存的相关文章

100行Java代码构建一个线程池

在现代的操作系统中,有一个很重要的概念――线程,几乎所有目前流行的操作系统都支持线程,线程来源于操作系统中进程的概念,进程有自己的虚拟地址空间以及正文段.数据段及堆栈,而且各自占有不同的系统资源(例如文件.环境变量等等).与此不同,线程不能单独存在,它依附于进程,只能由进程派生.如果一个进程派生出了两个线程,那这两个线程共享此进程的全局变量和代码段,但每个线程各拥有各自的堆栈,因此它们拥有各自的局部变量,线程在UNIX系统中还被进一步分为用户级线程(由进程自已来管理)和系统级线程(由操作系统的调

10行Python代码创建可视化地图

import vincent  world_countries = r'world-countries.json'  world = vincent.Map(width=1200, height=1000)  world.geo_data(projection='winkel3', scale=200, world=world_countries)  world.to_json(path)    当我开始建造Vincent时, 我的一个目的就是使得地图的建造尽可能合理化. 有一些很棒的pytho

将java代码转成c#代码

问题描述 下面是几行java代码,谁能转成c#代码:java.security.MessageDigestmd=java.security.MessageDigest.getInstance("MD5");StringBufferresult=newStringBuffer();try{for(byteb:md.digest(buffer.toString().getBytes("UTF-8"))){result.append(Integer.toHexString

java代码怎么写用命令行调用keytool生成证书

问题描述 java代码怎么写用命令行调用keytool生成证书 java代码怎么写用命令行调用keytool生成证书,最好具体一点,有注释最好 解决方案 http://blog.csdn.net/prstaxy/article/details/30050175http://blog.chinaunix.net/uid-17102734-id-2830223.html 解决方案二: java 调用 keytool 生成keystore 和 cer 证书Java调用命令行java调用命令行

字符串-java问题 17~20行的代码不能运行,也就是不能进行a==Mon[i]这个语句,求问是什么原因

问题描述 java问题 17~20行的代码不能运行,也就是不能进行a==Mon[i]这个语句,求问是什么原因 import java.util.Calendar; import java.util.Date; public class Date { public static void main(String[] args) { //以下代码是用来显示系统当前月份的第一天是星期几的 Calendar currentCal = Calendar.getInstance(); currentCal.

swing-怎样显示java代码的行号

问题描述 怎样显示java代码的行号 现在做一个代码收集器的一个软件(Swing做的),想对打开的代码提供行号显示功能,类似于eclipse上的显示代码行号,该如何操作?求帮助!! 解决方案 class类的左边缘鼠标右键 show line numbers

怎样在java 代码中通过ftp协议实现远程压缩文件 哪位指点一二,小弟不胜感激呀

问题描述 具体情况是这样的: 服务器端有好多xml文件有几个G,在客户端要下载下来,由于文件太大,若加上网络不好,就会下载失败. 考虑到xml文件压缩后会少的很多,就想在下载前将其压缩, 问题就在 怎样在客户端通过ftp协议将服务器端的xml文件压缩呢? 现在用的是commons-net 链接的 各位朋友都说说有啥好的解决方案莫 问题补充:能否通过写sheel脚本来执行服务器上的xml文件压缩呢? 若能实现,怎样在java代码中 执行sheel脚本 让其压缩服务器上的文件呢 解决方案 这个从理论

mysql-下面的Java代码有问题吗

问题描述 下面的Java代码有问题吗 public class Regist extends JFrame implements ActionListener { /** * */ private static final long serialVersionUID = 1L; private JPanel contentPane; private JTextField text_confirm; private JTextField text_usr; private JTextField t

redis-关于Redis数据库的java代码多线程读写性能问题,希望可以帮忙看看、、、

问题描述 关于Redis数据库的java代码多线程读写性能问题,希望可以帮忙看看... 渣渣一枚..由于项目关系,需要用到内存数据库来存key-value所以就开始研究redis这个数据库.现在已经把redis放在了CentOS的测试服务器上,然后通过网上的资料写了链接代码! 测试用了100个线程,每个线程插入10000条数据,结果竟然花了**200s**, 同事用memcached测试同样的数据只要了**20s** 而在linux中用redis自带的redis-benchmark查询性能 结果