LRU Cache数据结构的介绍可以参考前面的http://www.cnblogs.com/XP-Lee/p/3441555.html。
本文以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的反射机制去调用这个隐藏方法。