分享一个LRUMap的实现——来自apache common-collections框架

本文探讨了Apache Common Collections框架中的LRUMap实现,LRUMap是一种基于最近最少使用(LRU)算法的Map结构。通过示例代码展示了LRUMap在容量满时如何淘汰旧元素并插入新元素,同时解释了其内部结构和操作,如put和get操作如何维护LRU特性。
摘要由CSDN通过智能技术生成
               

今天主要分享一个LRUmap的实现。我们经常会用到需要使用map来保存数据的时候,由于map本身的映射高效,最适合做随机读取的存储结构。当然LRU算法是在有限大小的存储集合下的一种调度算法,即最近最少使用。对于一个给定大小限制的容器,如何分配资源就涉及到调度,而LRU就是一种经典的调度了,在容器中定义一个最后使用时间,当容器满时,再来新的元素,那么淘汰最近最少使用的元素,把新的元素替换之,这是最直接的思想。

apache common-collections框架里有一个LRUMap的实现,其继承自抽象的linkedmap和抽象的hashmap。下面给出一段测试代码,来看看LRU的直观效果:

   1: public static void main(String[] args) {
    
   2:         // TODO Auto-generated method stub
   3:         LRUMap map = new LRUMap(3);
   4:         map.put("1", 1);
   5:         map.put("2", 2);
   6:         //map.get("1");
   7:         map.put("3", 3);
   8:         map.put("4", 4);
   9:         
  10:         for(Iterator it = map.entrySet().iterator();it.hasNext();){
    
  11:             System.out.println(it.next());
  12:         }
  13:     }

使用的版本是common-collections3.2.1,直接执行,结果会显示

2=2

3=3

4=4

如果把第6行的注释打开,那么执行结果会是

1=1

3=3

4=4

这样就符合了LRU的原理,在调用了一次get后,1对应的数据不再是最近最少使用。

具体实现也颇有趣,LRUmap继承linkedmap,维护了一个linked list来保存内部数据

   1: /** Header in the linked list */
   2:     protected transient LinkEntry header;

linkentry又是一个循环双向的链表,且继承了hashentry,hashentry虽然也是commons框架自己实现,但是与jdk的实现同理,也是利用链接桶来预防冲突

   1: protected static class LinkEntry extends HashEntry {
    
   2:         /** The entry before this one in the order */
   3:         protected LinkEntry before;
   4:         /** The entry after this one in the order */
   5:         protected LinkEntry after;
   6:         
   7:         /**
   8:          * Constructs a new entry.
   9:          * 
  10:          * @param next  the next entry in the hash bucket sequence
  11:          * @param hashCode  the hash code
  12:          * @param key  the key
  13:          * @param value  the value
  14:          */
  15:         protected LinkEntry(HashEntry next, int hashCode, Object key, Object value) {
    
  16:             super(next, hashCode, key, value);
  17:         }
  18:     }

当进行put操作时,LRUMap会调用abstracthashmap的put方法,与传统一样,计算hashcode,在对应的hashcode桶定位index,然后做一个addmapping操作。本来在抽象类中的addmapping是传统的,等同于jdk中hashmap的addentry,但是LRUMap这里重写了addmapping,主要进行了map是否已满的判断,如果map未满,那么直接插入,否则,LRU将会定位到将被替换掉的entry的位置,然后做一个reuseMapping的操作,将该替换掉的entryremove,将新加进来的entry放到队尾。这样就完成了put操作。

进行get操作时,首先依据hashmap的原则找到entry,在返回value之前进行了LRU调整moveToMRU操作。该操作判断这个entry是否是队尾,如果是,那么什么都不用干,它就是最近被使用的,如果不是,那么调整它到队尾。

全部的源码见下:

   1: /*
   2:  *  Licensed to the Apache Soft
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值