Android之LinkedHashMap实现LRU
先看下LinkedHashMap的数据结构图
对于LinkedHashMap而言,它继承与HashMap、底层使用哈希表与双向链表来保存所有元素。其基本操作与父类HashMap相似,它通过重写父类相关的方法,来实现自己的链接列表特性。根据链表中元素的顺序可以分为:按插入顺序的链表,和按访问顺序(调用get方法)的链表。
LinkedHashMap采用的hash算法和HashMap相同,但是它重新定义了数组中保存的元素Entry,该Entry除了保存当前对象的引用外,还保存了其上一个元素before和下一个元素after的引用,从而在哈希表的基础上又构成了双向链接列表。
LinkedHashMap定义了排序模式accessOrder,该属性为boolean型变量,对于访问顺序,为true;对于插入顺序,则为false。
当有新元素加入Map的时候会调用Entry的addEntry方法,会调用removeEldestEntry方法,这里就是实现LRU元素过期机制的地方,默认的情况下removeEldestEntry方法只返回false表示元素永远不过期
public class Tester { private static int MAX=5; /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub HashMap<String,String> map = new LinkedHashMap<String, String>(MAX/2,0.5f,true) { @Override protected boolean removeEldestEntry(Map.Entry<String, String> eldest){ if(size()>MAX){ return true; } return false; } }; map.put("a", "a"); map.put("b", "b"); map.put("c", "c"); map.put("d", "d"); map.put("e", "e"); map.put("c", "c"); for (Map.Entry<String, String> entry : map.entrySet()) { System.out.print(entry.getValue() + ", "); } System.out.println(); map.get("b"); for (Map.Entry<String, String> entry : map.entrySet()) { System.out.print(entry.getValue() + ", "); } System.out.println(); map.put("f", "f"); for (Map.Entry<String, String> entry : map.entrySet()) { System.out.print(entry.getValue() + ", "); } System.out.println(); } }
a, b, d, e, c,
a, d, e, c, b,
d, e, c, b, f,
可见最新加入的或者最近get过的就会往最后放,如果put数目大于max,就会把头上那个去掉,然后f加到最后,其他往前移。
所以说不只是put,get也会把Entry往后方,越往后的说明最近才访问过的,越往前的说明最近最少访问的,这就实现了一个简单的LRU。
参考: