分享一个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 ,