本文主要介绍Android缓存机制LruCache,通过示例代码非常详细的介绍,对于大家的学习或者工作都有一定的参考价值。有需要的朋友下面和边肖一起学习。
概述
LruCache的核心原则是有效利用LinkedHashMap。LRUCACHE中有一个LinkedHashMap成员变量,有四个值得注意的方法:construction method、get、put和trimToSize。
LRU(最近最少使用)缓存算法应运而生。LRU是最近最少使用的算法,其核心思想是当缓存满时,最近最少使用的缓存对象将首先被淘汰。使用LRU算法的缓存有两种:LrhCache和DisLruCache,分别用于实现内存缓存和硬盘缓存。他们的核心思想是LRU缓存算法。
LRU原理
LruCache的核心思想很好理解,就是维护一个缓存对象的列表,其中对象的列表是按照访问的顺序排列的,也就是一直没有被访问的对象会被放在队列的最前面,很快就会被淘汰。最近访问过的对象将被放在队列的末尾并最终被消除。(在队列末尾添加元素,在队列开头删除元素)
LruCache实际上使用的是LinkedHashMap双向链表结构。现在,我们来分析LinkedHashMap的用法。
1.施工方法:
public linked hashmap(int initial capacity,
浮动负载系数,
布尔辅助指令){
super(initialCapacity,load factor);
this.accessOrder=accessOrder
}
当accessOrder为true时,该集合中元素的顺序将是访问顺序,即在访问之后,该元素将被放置在集合的后面。
例如:
LinkedHashMap Integer,Integer map=new LinkedHashMap (0,0.75f,true);
map.put(0,0);
map.put(1,1);
map.put(2,2);
map.put(3,3);
map . get(1);
map . get(2);
对于(图。Entry Integer,Integer entry: map.entrySet()) {
system . out . println(entry . getkey()':' entry . getvalue());
}
输出结果:
0:0
3:3
1:1
2:2
让我们具体看一下LruCache源代码,如何应用LinkedHashMap来添加、获取和删除缓存:
/**
* @param maxSize对于不覆盖{@link #sizeOf}的缓存,这是
*缓存中的最大条目数。对于所有其他缓存,
*这是此缓存中条目大小的最大总和。
*/
public LruCache(int maxSize) {
if (maxSize=0) {
抛出新的IllegalArgumentException(' maxSize=0 ');
}
this.maxSize=maxSize
this.map=new LinkedHashMapK,V(0,0.75f,true);//accessOrder设置为true
}
从LruCache的构造函数可以看出,使用的是LinkedHashMap的访问顺序。
2.put()方法
/**
*缓存{@code key}的{@code value}。该值被移动到的头部
*队列。
*
* @返回由{@code key}映射的上一个值。
*/
公共最终V put(K键,V值){
If (key==null || value==null) {//为null;它不能为空。
抛出新的NullPointerException(' key==null | | value==null ');
}
v以前的;
同步(这){
putCount//插入缓存对象加1
size=safeSizeOf(键,值);//增加现有缓存的大小
previous=map.put(key,value);//将缓存对象添加到地图中
如果(上一篇!=null) {//如果已经有一个缓存对象,缓存大小恢复到之前的大小。
size -=safeSizeOf(key,previous);
}
}
如果(上一篇!=null) {//entryRemoved()是空方法,可以自己实现。
entryRemoved(false,key,previous,value);
}
trim tosize(maxSize);//调整缓存大小(key方法)
返回上一个;
}
可以看出,put()方法对于调用trimToSize()方法以确保添加缓存对象后内存不超过maxSize非常重要。
3.trimToSize方法
再次查看trimToSize()方法:
/**
*删除最早的条目,直到剩余条目总数达到或
*低于要求的大小。
*
* @param maxSize返回前缓存的最大大小。可能是-1
*甚至驱逐0大小的元素。
*/
public void trim tosize(int maxSize){
While (true) {//无限循环
k键;
v值;
同步(这){
//如果地图为空并且缓存大小不等于0或者缓存大小小于0,抛出异常
if (size 0 || (map.isEmpty() size!=0)) {
抛出新的IllegalStateException(getClass().getName()。sizeOf()报告了不一致的结果!);
}
//如果缓存大小大小小于最大缓存,或者地图为空,不需要再删除缓存对象,跳出循环
if (size=maxSize) {
打破;
}
//取出地图中最老的映射
地图EntryK,V toEvict=map。老大();
if (toEvict==null) {
打破;
}
key=toe vict。getkey();
值=toe vict。getvalue();
地图.移除(键);
size -=safeSizeOf(key,value);
驱逐计数;
}
entryRemoved(true,key,value,null);
}
}
trimToSize()方法不断地删除LinkedHashMap中队头的元素,即近期最少访问的,直到缓存大小小于最大值。
4. get方法
当调用鲁卡奇的获取()方法获取集合中的缓存对象时,就代表访问了一次该元素,将会更新队列,保持整个队列是按照访问顺序排序。这个更新过程就是在LinkedHashMap中的获取()方法中完成的。
接着看鲁卡奇的获取()方法
/**
*返回{@code key}的值,如果它存在于缓存中或者可以
*由{@code #create}创建。如果返回了一个值,它将被移动到
*队列的最前面。如果一个值没有被缓存并且不能
*被创建。
*/
公共最终V get(K键){
if (key==null) {//key不能为空
抛出新的NullPointerException(' key==null ');
}
v地图值
同步(这){
/获取对应的缓存对象
地图值=地图。get(键);
if (mapValue!=null) {
点击次数;
返回地图值
}
错误计数;
}
看到鲁卡奇的得到方法实际是调用了LinkedHashMap的得到方法:
公V get(对象键){
LinkedHashMapEntryK,V e=(LinkedHashMapEntryK,V)getEntry(key);
if (e==null)
返回空
e。记录访问(this);//实现排序的关键
返回e .价值
}
再接着看LinkedHashMapEntry的记录访问方法:
/**
*每当值为
*由Map.get读取或由Map.set修改。
*如果封闭映射是按访问顺序的,它会移动条目
*到列表的末尾;否则,它什么也不做。
*/
void recordAccess(HashMapK,V m) {
LinkedHashMapK,V lm=(LinkedHashMapK,V)m;
if (lm.accessOrder) {//判断是否是访问顺序
lm.modCount
移除();//删除此元素
加在前面(lm。表头);//将此元素移到队尾
}
}
记录访问方法的作用是如果附属订单为没错,把已存在的进入在调用得到读取或者设置编辑后移到队尾,否则不做任何操作。
也就是说:这个方法的作用就是将刚访问过的元素放到集合的最后一位
总结:
鲁卡奇的核心原理就是对LinkedHashMap对象的有效利用。在构造方法中设置maxSize并将附属订单设为没错,执行得到后会将访问元素放到队列尾,放操作后则会调用trimToSize维护LinkedHashMap的大小不大于最大尺寸。
以上所述是小编给大家介绍的机器人缓存机制鲁卡奇详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。