标签:
在学习LRU算法的时候,看到LruCache源码实现是基于LinkedHashMap,今天学习一下LinkedHashMap的好处以及如何实现lru缓存机制的。
LRU这个算法就是把最近一次使用时间离现在时间最远的数据删除掉,而实现LruCache将会频繁的执行插入、删除等操作,我们就会想到使用LinkedList,但是我们又要基于Key-Value来保存数据,这个时候我们就会想起HashMap,但是HashMap不能像linkedList那样保留数据的插入顺序,如果要使用HashMap的话可以使用它的一个子类LinkedHashMap。
LinkedHashMap是Map接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变, LinkedHashMap实现与HashMap的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。根据链表中元素的顺序可以分为:按插入顺序的链表,和按访问顺序(调用get方法)的链表。默认是按插入顺序排序,如果指定按访问顺序排序,那么调用get方法后,会将这次访问的元素移至链表尾部,不断访问可以形成按访问顺序排序的链表。 可以重写removeEldestEntry方法返回true值指定插入元素时移除最老的元素。更多关于LinkedHashMap的知识介绍请查看这篇博客,博客地址:http://www.cnblogs.com/children/archive/2012/10/02/2710624.html
因为我们这里为了实现LRU算法,排序方式 设置为true 访问顺序排序
int initialCapacity = 10;//初始化容量 float loadFactor = 0.75f;//加载因子,一般是 0.75f boolean accessOrder = true;//排序方式 false 基于插入顺序 true 基于访问顺序 Map<String, Integer> map = new LinkedHashMap<>(initialCapacity, loadFactor, accessOrder);
具体看下效果:
for (int i = 0; i < 10; i++) { map.put(String.valueOf(i), i); } //访问前顺序 for (Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator(); it.hasNext(); ) { Map.Entry<String, Integer> next = it.next(); Log.e(TAG, "linkedMap--before-->" + next.getKey()); } //模拟访问 map.get("5"); //访问后数据 for (Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator(); it.hasNext(); ) { Map.Entry<String, Integer> next = it.next(); Log.e(TAG, "linkedMap--after-->" + next.getKey()); } }
运行结果发现访问过的5未知发生了变化 说明是基于访问排序的。我们接下来再看下如何移除过期的。
final int initialCapacity = 10;//初始化容量 float loadFactor = 0.75f;//加载因子,一般是 0.75f boolean accessOrder = true;//排序方式 false 基于插入顺序 true 基于访问顺序 //Map<String, Integer> map = new LinkedHashMap<>(initialCapacity, loadFactor, accessOrder); Map<String, Integer> map = new LinkedHashMap(initialCapacity, loadFactor, accessOrder) { @Override protected boolean removeEldestEntry(Entry eldest) { return size() > initialCapacity; } }; for (int i = 0; i < 15; i++) { map.put(String.valueOf(i), i); } //访问前顺序 for (Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator(); it.hasNext(); ) { Map.Entry<String, Integer> next = it.next(); Log.e(TAG, "linkedMap--before-->" + next.getKey()); }
我们容量定的10个,我们插入15个 我们发现最先插入的五个不见了,说明LRU算法起到效果了。
标签:
原文地址:http://www.cnblogs.com/whoislcj/p/5552421.html