public class LurCache<K, V> {
private final LinkedHashMap<K, V> map;
private int size; // 已经存储的大小
private int maxSize; // 规定的最大存储空间
private int putCount; // put的次数
private int createCount; // create的次数
private int evictionCount; // 回收的次数
private int hitCount; // 命中的次数
private int missCount; // 丢失的次数 public LruCache(int maxSize) {
if (maxSize <= ) {
throw new IllegalArgumentException("maxSize <= 0");
}
this.maxSize = maxSize;
this.map = new LinkedHashMap<K, V>(, 0.75f, true);
} public final V get(K key) {
if (key == null) {
throw new NullPointerException("key == null");
} V mapValue;
synchronized (this) {
mapValue = map.get(key);
if (mapValue != null) {
hitCount++; // 命中
return mapValue;
}
missCount++; // 丢失
} V createdValue = create(key);
if (createdValue == null) {
return null;
} synchronized (this) {
createCount++;// 创建++
mapValue = map.put(key, createdValue); if (mapValue != null) {
// There was a conflict so undo that last put
// 如果前面存在oldValue,那么撤销put()
map.put(key, mapValue);
} else {
size += safeSizeOf(key, createdValue);
}
}
if (mapValue != null) {
entryRemoved(false, key, createdValue, mapValue);
return mapValue;
} else {
trimToSize(maxSize);
return createdValue;
}
} public final V put(K key, V value) {
if (key == null || value == null) {
throw new NullPointerException("key == null || value == null");
} V previous;
synchronized (this) {
putCount++;
size += safeSizeOf(key, value);
previous = map.put(key, value);
if (previous != null) { //返回的先前的value值
size -= safeSizeOf(key, previous);
}
} if (previous != null) {
entryRemoved(false, key, previous, value);
} trimToSize(maxSize);
return previous;
}
//清空cache空间
private void trimToSize(int maxSize) {
while (true) {
K key;
V value;
synchronized (this) {
if (size < || (map.isEmpty() && size != )) {
throw new IllegalStateException(getClass().getName()
+ ".sizeOf() is reporting inconsistent results!");
} if (size <= maxSize) {
break;
} Map.Entry<K, V> toEvict = map.entrySet().iterator().next();
if (toEvict == null) {
break;
} key = toEvict.getKey();
value = toEvict.getValue();
map.remove(key);
size -= safeSizeOf(key, value);
evictionCount++;
} entryRemoved(true, key, value, null);
}
}
//删除key相应的cache项,返回相应的value
public final V remove(K key) {
if (key == null) {
throw new NullPointerException("key == null");
} V previous;
synchronized (this) {
previous = map.remove(key);
if (previous != null) {
size -= safeSizeOf(key, previous);
}
} if (previous != null) {
entryRemoved(false, key, previous, null);
} return previous;
}
//当item被回收或者删掉时调用。该方法当value被回收释放存储空间时被remove调用, 或者替换item值时put调用,默认实现什么都没做。
//true: 为释放空间被删除;false: put或remove导致
protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {} protected V create(K key) {
return null;
} private int safeSizeOf(K key, V value) {
int result = sizeOf(key, value);
if (result < ) {
throw new IllegalStateException("Negative size: " + key + "=" + value);
}
return result;
} protected int sizeOf(K key, V value) {
return ;
}
//清空cache
public final void evictAll() {
trimToSize(-); // -1 will evict 0-sized elements
} public synchronized final int size() {
return size;
} public synchronized final int maxSize() {
return maxSize;
} public synchronized final int hitCount() {
return hitCount;
} public synchronized final int missCount() {
return missCount;
} public synchronized final int createCount() {
return createCount;
} public synchronized final int putCount() {
return putCount;
} //返回被回收的数量
public synchronized final int evictionCount() {
return evictionCount;
}
//返回当前cache的副本,从最近最少访问到最多访问
public synchronized final Map<K, V> snapshot() {
return new LinkedHashMap<K, V>(map);
} public synchronized final String toString() {
int accesses = hitCount + missCount;
int hitPercent = accesses != ? ( * hitCount / accesses) : ;
return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]",
maxSize, hitCount, missCount, hitPercent);
}
}

Android LruCache类分析的更多相关文章

  1. Android LayoutInflater 类分析

    作为一名Android开发者,写页面是最普通不过的事情了,在编写页面的时候,系统给提供了两种形式,一种形式是通过XML的方式进行编写,还有一种形式是通过Java代码直接编写   我们知道Android ...

  2. Android LRUCache简介

    LRU Cache数据结构的介绍可以参考前面的http://www.cnblogs.com/XP-Lee/p/3441555.html. 本文以Android LRUCache来做一个简单的介绍.我们 ...

  3. Android的消息循环机制 Looper Handler类分析

    Android的消息循环机制 Looper Handler类分析 Looper类说明   Looper 类用来为一个线程跑一个消息循环. 线程在默认情况下是没有消息循环与之关联的,Thread类在ru ...

  4. 「Android」消息驱动Looper和Handler类分析

    Android系统中的消息驱动工作原理: 1.有一个消息队列,可以往这个消息队列中投递消息; 2.有一个消息循环,不断的从消息队列中取得消息,然后处理. 工作流程: 1.事件源将待处理的消息加入到消息 ...

  5. 源码分析篇 - Android绘制流程(三)requestLayout()与invalidate()流程及Choroegrapher类分析

    本文主要探讨能够触发performTraversals()执行的invalidate().postInvalidate()和requestLayout()方法的流程.在调用这三个方法到最后执行到per ...

  6. Android APP性能分析方法及工具

    近期读到<Speed up your app>一文.这是一篇关于Android APP性能分析.优化的文章.在这篇文章中,作者介绍他的APP分析优化规则.使用的工具和方法.我觉得值得大家借 ...

  7. Android源码分析-全面理解Context

    前言 Context在android中的作用不言而喻,当我们访问当前应用的资源,启动一个新的activity的时候都需要提供Context,而这个Context到底是什么呢,这个问题好像很好回答又好像 ...

  8. Android 服务类Service 的详细学习

    http://blog.csdn.net/vipzjyno1/article/details/26004831 Android服务类Service学习四大组建   目录(?)[+] 什么是服务 服务有 ...

  9. cocos2d-x for android:SimpleGame分析

    cocos2d-x for android:SimpleGame分析 作为cocos2d-x的标配DEMO,SimpleGame可算是给入门学cocos2d-x的俺们这些新手门学习的对象了,那么来分析 ...

随机推荐

  1. Dom4j 查找节点或属性

    Dom4j  查找节点或属性 例如 1 查找下面xml中的student节点的age属性, xpathstr="/students/student/@age"; 2 查找下面xml ...

  2. C++11 volatile 类型

    volatile作用: 作为指令关键字,确保本条指令不会受到编译器的优化而省略,而且要求每次直接读值. 定义: volatile int nTest; volatile关键字是一种类型修饰符,用它声明 ...

  3. BZOJ——T 1113: [Poi2008]海报PLA

    http://www.lydsy.com/JudgeOnline/problem.php?id=1113 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: ...

  4. 读MBA经历回想(下)做法决定结果——北漂18年(49)

    上期聊了目的决定了手段,这次说说详细做法决定了最后的结果. 差额面试被淘汰的高分学员 2005年,是北京邮电大学工商管理学入学考试第一个差额淘汰的年份.意思是过分数线(165分)的人数超过了录取人数, ...

  5. Lua刚開始学习的人(一)--Lua 简单教学

    近期因为工作原因.临时木有<Oracle起步学习>续集.领导知道学习下Lua脚本语言.看了一周了.趁热打铁,留下点实用的东西吧. 本系列会主要针对宿主语言为 Delphi,原理都是一样的, ...

  6. matlab中tic和toc使用方法

    tic和toc用来记录matlab命令运行的时间.  tic用来保存当前时间,而后使用toc来记录程序完毕时间. 两者往往结合使用,使用方法例如以下: 程序代码: tic  operations  t ...

  7. 如何优雅的写UI——(6)内存泄漏

    控件讲了这么久,其实我的程序有两个Bug不知道大家有没有发现,这两个Bug都不会报错,对程序运行来说都没有阻碍,但是这种Bug对整个代码来说是一个很大的安全隐患. 什么是内存泄漏 内存泄漏(Memor ...

  8. 徒弟们对话,遇到sb领导,离职吧

     由于涉及私密,所以qq号做了干扰.见谅. 非常多人以为在公司,你优化了几十个sql老板就给你涨工资了.或者你bbed搞点特殊恢复就涨工资了. 或者解决某些棘手问题就涨工资了. 那是不正确的. 遇 ...

  9. php课程 12-41 多态是什么

    php课程 12-41 多态是什么 一.总结 一句话总结:一种请求,多种响应(根据参数类型和数量) 1.function useUsb(Usb $usb){}这句话是什么意思? 判断$usb参数是否实 ...

  10. 2.1 Producer API官网剖析(博主推荐)

    不多说,直接上干货! 一切来源于官网 http://kafka.apache.org/documentation/ 2.1 Producer API 2.1.生产者API 我们鼓励所有新开发的程序使用 ...