当前位置:web 服务器 > Apache >>

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

今天主要分享一个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 Software Foundation (ASF) under one or more
   3:  *  contributor license agreements.  See the NOTICE file distributed with
   4:  *  this work for additional information regarding copyright ownership.
   5:  *  The ASF licenses this file to You under the Apache License, Version 2.0
   6:  *  (the "License"); you may not use this file except in compliance with
   7:  *  the License.  You may obtain a copy of the License at
   8:  *
   9:  *      http://www.apache.org/licenses/LICENSE-2.0
  10:  *
  11:  *  Unless required by applicable law or agreed to in writing, software
  12:  *  distributed under the License is distributed on an "AS IS" BASIS,
  13:  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14:  *  See the License for the specific language governing permissions and
  15:  *  limitations under the License.
  16:  */
  17: package org.apache.commons.collections.map;
  18: 
  19: import java.io.IOException;
  20: import java.io.ObjectInputStream;
  21: import java.io.ObjectOutputStream;
  22: import java.io.Serializable;
  23: import java.util.Map;
  24: 
  25: import org.apache.commons.collections.BoundedMap;
  26: 
  27: /**
  28:  * A <code>Map</code> implementation with a fixed maximum size which removes
  29:  * the least recently used entry if an entry is added when full.
  30:  * <p>
  31:  * The least recently used algorithm works on the get and put operations only.
  32:  * Iteration of any kind, including setting the value by iteration, does not
  33:  * change the order. Queries such as containsKey and containsValue or access
  34:  * via views also do not change the order.
  35:  * <p>
  36:  * The map implements <code>OrderedMap</code> and entries may be queried using
  37:  * the bidirectional <code>OrderedMapIterator</code>. The order returned is
  38:  * least recently used to most recently used. Iterators from map views can
  39:  * also be cast to <code>OrderedIterator</code> if required.
  40:  * <p>
  41:  * All the available iterators can be reset back to the start by casting to
  42:  * <code>ResettableIterator</code> and calling <code>reset()</code>.
  43:  * <p>
  44:  * <strong>Note that LRUMap is not synchronized and is not thread-safe.</strong>
  45:  * If you wish to use this map from multiple thread

补充:软件开发 , Java ,
Apache
IIS
Nginx
Tomcat
如果你遇到web 服务器难题:
请访问www.zzzyk.com 试试
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,