LRU Cache数据结构的介绍可以参考前面的http://blog.csdn.net/xplee0576/article/details/22200537。
本文以Android LRUCache来做一个简单的介绍。我们已经知道LRU Cache是一个hash map+双向链表的数据结构,那么在Android的Java自然也逃不出这个框,谷歌在Android3.1(v4 library也支持)之后提供了一个封装此数据结构实现的LRUCache类。
Android LRUCache访问数据
LRUCache暴露了三个线程安全的方法get(K)、put(K)和remove(K),通过这三个方法,我们可以操作cache数据。get(K)或者put(K),它们始终都会将K对应的V移到链表头部,这样链表尾部就成为了最久没有使用的数据结点。remove(K)用来删除数据,通过调用entryRemoved(boolean evicted, K key, V oldValue, V newValue)达到进一步的数据清理。
既然LRUCache是用来对缓存大小裁剪移除的,那以上描述除了remove(K)其它都没有涉及到关于缓存的大小检查啊,假设我不断的插入数据怎么办呢?下面接着缓存大小裁剪移除,做一个补充。在LRUCache中,我们无论调用get(K)还是put(K),它们都会调用方法trimToSize(int maxSize)进行缓存大小计算,当缓存大小超过maxSize时,就会调用entryRemoved(boolean evicted, K key, V oldValue, V newValue)清理数据。因此,使用LRUCache的get(K)或者put(K)访问数据时,其缓存大小将始终被维持在maxSize之下,当快要超过时链表尾部的数据会因为这套算法被删除清理。
重写方法
Android LRUCache暴露三个方法可供重写。
必须重写方法:
- sizeOf(K, V):每个V的大小
- entryRemoved(boolean evicted, K key, V oldValue, V newValue):回收缓存,只需要对newValue进行回收就可以
看实际需求可重写也可不重写的方法:
- creat(K):当map中没有K映射的V,该方法才会被get(K)方法调用。若creat(K)返回null,get(K)方法的调用点后续指令将直接以null的形式返回,不做任何处理;否则,就同以creat(K)的返回值作为K对应的V插入LRUCache。
隐藏方法
Android LRUCache类还提供了一个权限为public的隐藏方法resize(int),该隐藏方法也是线程安全的,可以用来重置LRUCache的最大缓存。由于是隐藏方法,我们在代码中是无法显示的去调用,唯一可行的办法就是通过JAVA的反射机制去调用这个隐藏方法。
Android LruCache源码
package android.util;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* A cache that holds strong references to a limited number of values. Each time
* a value is accessed, it is moved to the head of a queue. When a value is
* added to a full cache, the value at the end of that queue is evicted and may
* become eligible for garbage collection.
* Cache保存一个强引用来限制内容数量,每当Item被访问的时候,此Item就会移动到队列的头部。
* 当cache已满的时候加入新的item时,在队列尾部的item会被回收。
* <p>If your cached values hold resources that need to be explicitly released,
* override {@link #entryRemoved}.
* 如果你cache的某个值需要明确释放,重写entryRemoved()
* <p>If a cache miss should be computed on demand for the corresponding keys,
* override {@link #create}. This simplifies the calling code, allowing it to
* assume a value will always be returned, even when there's a cache miss.
* 如果key相对应的item丢掉啦,重写create().这简化了调用代码,即使丢失了也总会返回。
* <p>By default, the cache size is measured in the number of entrie