Java 自定义实现 LRU 缓存算法

开发 后端 算法
LinkedHashMap继承自HashMap,内部提供了一个removeEldestEntry方法,该方法正是实现LRU策略的关键所在, 且HashMap内部专门为LinkedHashMap提供了3个专用回调方法,afterNodeAccess、 afterNodeInsertion、afterNodeRemoval,这3个方法的字面意思非常容易理解,就是节点访问后、节点插入后、节点删除后 分别执行的行为。

背景

LinkedHashMap继承自HashMap,内部提供了一个removeEldestEntry方法,该方法正是实现LRU策略的关键所在, 且HashMap内部专门为LinkedHashMap提供了3个专用回调方法,afterNodeAccess、 afterNodeInsertion、afterNodeRemoval,这3个方法的字面意思非常容易理解,就是节点访问后、节点插入后、节点删除后 分别执行的行为。基于以上行为LinkedHashMap就可以实现一个LRUCache的功能了。

[[142638]]

关于LinkedHashMap的eldest:eldest字面意思为最老的,LinkedHashMap中有个叫做accessOrder的字 段,当accessOrder为true时表示LinkedHashMap内部节点按照访问次数排序,最老的节点也就是访问最少的节点。当 accessOrder为false时表示LinkedHashMap内部节点按照插入顺序排序,最老的节点也就是最早插入的节点,该值默认为 false。

实现

自己实现LRUCache只需覆盖removeEldestEntry这个方法即可,代码如下

private static class LRUCache<K, V> extends LinkedHashMap<K, V>
{
  private static final long serialVersionUID = -9111855653176630846L;
  private static int MAX_ELEMENTS;

  public LRUCache(int initCap, int maxSize) throws IllegalArgumentException
  {
   super(initCap, 0.75f, true);
   if (maxSize < 0)
    throw new IllegalArgumentException();
   MAX_ELEMENTS = maxSize;
  }

  @Override
  protected boolean removeEldestEntry(Map.Entry<K, V> eldest)
  {
   return size() > MAX_ELEMENTS;
  }
}

以上代码需要一个MAX_ELEMENTS变量限制***存储节点个数,插入节点时判断 如果当 前节点个数已经超过了这个值则会根据LRU策略将访问最少的那个节点删除,这里需要注意,默认LinkedHashMap保证的是插入顺序,也就是节点按 照插入先后来排序的,所以就算删除也是删除***插入的节点,但是我们在构造函数中传入了一个true,这个参数决定了LinkedHashMap内部的节 点按照什么方式排序,参数为true时说明内部节点按照最近访问的时间排序,为false时说明按照插入顺序排序。至此已完成了一个简易的 LRUCache实现。

注意

由于LinkedHahsMap本身实现不是线程安全的,也就是说这个LRUCache也不是线程安全的,如果想要能多线程访问的话,可以这样使用 它:LRUCache cache = Collections.synchronizedMap(new LRUCache(10, 10))。这样cache就可以在多线程下执行get/put等操作了,但是,用这种方式得到的cache在多线程遍历时还是不安全的。所以不能在多线程 下遍历cache,官方文档也建议在遍历synchronizedmap时使用map本身做同步。

责任编辑:王雪燕 来源: codeceo
相关推荐

2022-06-17 07:49:14

缓存LRU

2020-02-19 19:18:02

缓存查询速度淘汰算法

2020-10-30 11:30:15

Least Recen

2009-07-23 11:11:18

LRU缓存

2022-05-18 07:44:13

自定义菜单前端

2009-09-07 22:00:15

LINQ自定义

2011-12-16 14:23:51

Java

2021-09-26 05:02:00

缓存Ehcache用法

2023-10-19 09:14:34

Java开发

2015-02-12 15:33:43

微信SDK

2009-07-06 16:20:50

JSP自定义标签

2009-06-17 16:00:03

Hibernate自定

2022-12-07 08:56:27

SpringMVC核心组件

2009-09-03 13:34:03

.NET自定义控件

2022-03-01 16:09:06

OpenHarmon鸿蒙单选组件

2022-04-01 15:59:22

SQLPostgreSQL审计

2023-01-03 07:40:27

自定义滑块组件

2013-01-09 17:22:38

Android开发Camera

2023-10-24 13:48:50

自定义注解举值验证

2015-07-15 10:19:16

Java代码使用缓存
点赞
收藏

51CTO技术栈公众号