1. package android.util;
  2.  
  3. import java.util.LinkedHashMap;
  4. import java.util.Map;
  5.  
  6. /**
  7. * A cache that holds strong references to a limited number of values. Each time
  8. * a value is accessed, it is moved to the head of a queue. When a value is
  9. * added to a full cache, the value at the end of that queue is evicted and may
  10. * become eligible for garbage collection.
    一个cache缓冲区,维护有限个值的强引用。当一个值被命中时,它被移到队列的头部???确定有移动么
    当一个值被加入一个已满的cache中时,队列最后一个值被舍弃。可能会被垃圾回收
    * <p>If your cached values hold resources that need to be explicitly released,
  11. * override {@link #entryRemoved}.
    如果你缓存的值中有必须被释放的资源,需要override  entryRemoved方法
    * <p>If a cache miss should be computed on demand for the corresponding keys,
  12. * override {@link #create}. This simplifies the calling code, allowing it to
  13. * assume a value will always be returned, even when there's a cache miss.
    如果一次cache未命中时,同样需要返回。 需要override create()方法。
    这使调用简化:不管是不是命中,都返回一个值。
  14.  
  15. 因为当前的create方法返回的是个null。当你没get到的时候,会调用create方法。在当前情况下,返回null会直接return null。
    不会往后执行之后的创建键值对,并返回的操作。
  16.  
  17. 但是如果你重写了create(),使其返回的不是null,则后边的操作会执行。调用get(key),value值被返回。
    * <p>By default, the cache size is measured in the number of entries. Override
  18. * {@link #sizeOf} to size the cache in different units. For example, this cache
  19. * is limited to 4MiB of bitmaps:
    默认情况下,一个cache的大小,是以实体的个数来衡量的。因为当前的sizeOf() 方法返回的是1,也就是每个entry大小是1
    你可以override  sizeof方法,改变cache 的最小单元大小。
    例如,下边这个cache 限制为最大4MiB的bitmap cache
    每个单元的大小就不是1了,而是bitmap的大小。
  20. * <pre> {@code
  21. * int cacheSize = 4 * 1024 * 1024; // 4MiB
  22. * LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) {
  23. * protected int sizeOf(String key, Bitmap value) {
  24. * return value.getByteCount();
  25. * }
  26. * }}</pre>

  27. LRUCache类是线程安全的。多个cache操作时候。要synchronize这个cache
  28.  
  29. * <p>This class is thread-safe. Perform multiple cache operations atomically by
  30. * synchronizing on the cache: <pre> {@code
  31. * synchronized (cache) {
  32. * if (cache.get(key) == null) {
  33. * cache.put(key, value);
  34. * }
  35. * }}</pre>

  36. 这个类不允许传入的key和value是空。
    get put remove返回null,代表这个key不再cache中
  37.  
  38. * <p>This class does not allow null to be used as a key or value. A return
  39. * value of null from {@link #get}, {@link #put} or {@link #remove} is
  40. * unambiguous: the key was not in the cache.
  41. *
  42. * <p>This class appeared in Android 3.1 (Honeycomb MR1); it's available as part
  43. * of <a href="http://developer.android.com/sdk/compatibility-library.html">Android's
  44. * Support Package</a> for earlier releases.
  45. */
  46. public class LruCache<K, V> {
  47. private final LinkedHashMap<K, V> map;
  48.  
  49. /** Size of this cache in units. Not necessarily the number of elements. */
  50. private int size;
  51. private int maxSize;
  52.  
  53. private int putCount;
  54. private int createCount;
  55. private int evictionCount;
  56. private int hitCount;
  57. private int missCount;
  58.  
  59. /**
  60. * @param maxSize for caches that do not override {@link #sizeOf}, this is
  61. * the maximum number of entries in the cache. For all other caches,
  62. * this is the maximum sum of the sizes of the entries in this cache.
  63. */
  64. public LruCache(int maxSize) {
  65. if (maxSize <= 0) {
  66. throw new IllegalArgumentException("maxSize <= 0");
  67. }
  68. this.maxSize = maxSize;
  69. this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
  70. }
  71.  
  72. /**
  73. * Sets the size of the cache.
  74. * @param maxSize The new maximum size.
  75. *
  76. * @hide
  77. */
  78. public void resize(int maxSize) {
  79. if (maxSize <= 0) {
  80. throw new IllegalArgumentException("maxSize <= 0");
  81. }
  82.  
  83. synchronized (this) {
  84. this.maxSize = maxSize;
  85. }
  86. trimToSize(maxSize);
  87. }
  88.  
  89. /**
  90. * Returns the value for {@code key} if it exists in the cache or can be
  91. * created by {@code #create}. If a value was returned, it is moved to the
  92. * head of the queue. This returns null if a value is not cached and cannot
  93. * be created.
  94. */
  95. public final V get(K key) {
  96. if (key == null) {
  97. throw new NullPointerException("key == null");
  98. }
  99.  
  100. V mapValue;
  101. synchronized (this) {
  102. mapValue = map.get(key);
  103. if (mapValue != null) {
  104. hitCount++;
  105. return mapValue;
  106. }
  107. missCount++;
  108. }
  109.  
  110. /*
  111. * Attempt to create a value. This may take a long time, and the map
  112. * may be different when create() returns. If a conflicting value was
  113. * added to the map while create() was working, we leave that value in
  114. * the map and release the created value.
  115. */
  116.  
  117. V createdValue = create(key);
  118. if (createdValue == null) {
  119. return null;
  120. }
  121.  
  122. synchronized (this) {
  123. createCount++;
  124. mapValue = map.put(key, createdValue);
  125.  
  126. if (mapValue != null) {
  127. // There was a conflict so undo that last put
  128. map.put(key, mapValue);
  129. } else {
  130. size += safeSizeOf(key, createdValue);
  131. }
  132. }
  133.  
  134. if (mapValue != null) {
  135. entryRemoved(false, key, createdValue, mapValue);
  136. return mapValue;
  137. } else {
  138. trimToSize(maxSize);
  139. return createdValue;
  140. }
  141. }
  142.  
  143. /**
  144. * Caches {@code value} for {@code key}. The value is moved to the head of
  145. * the queue.
  146. *
  147. * @return the previous value mapped by {@code key}.
  148. */
  149. public final V put(K key, V value) {
  150. if (key == null || value == null) {
  151. throw new NullPointerException("key == null || value == null");
  152. }
  153.  
  154. V previous;
  155. synchronized (this) {
  156. putCount++;
  157. size += safeSizeOf(key, value);
  158. previous = map.put(key, value);
  159. if (previous != null) {
  160. size -= safeSizeOf(key, previous);
  161. }
  162. }
  163.  
  164. if (previous != null) {
  165. entryRemoved(false, key, previous, value);
  166. }
  167.  
  168. trimToSize(maxSize);
  169. return previous;
  170. }
  171.  
  172. /**
  173. * Remove the eldest entries until the total of remaining entries is at or
  174. * below the requested size.
  175. *
  176. * @param maxSize the maximum size of the cache before returning. May be -1
  177. * to evict even 0-sized elements.
  178. */
  179. public void trimToSize(int maxSize) {
  180. while (true) {
  181. K key;
  182. V value;
  183. synchronized (this) {
  184. if (size < 0 || (map.isEmpty() && size != 0)) {
  185. throw new IllegalStateException(getClass().getName()
  186. + ".sizeOf() is reporting inconsistent results!");
  187. }
  188.  
  189. if (size <= maxSize) {
  190. break;
  191. }
  192.  
  193. Map.Entry<K, V> toEvict = map.eldest();
  194. if (toEvict == null) {
  195. break;
  196. }
  197.  
  198. key = toEvict.getKey();
  199. value = toEvict.getValue();
  200. map.remove(key);
  201. size -= safeSizeOf(key, value);
  202. evictionCount++;
  203. }
  204.  
  205. entryRemoved(true, key, value, null);
  206. }
  207. }
  208.  
  209. /**
  210. * Removes the entry for {@code key} if it exists.
  211. *
  212. * @return the previous value mapped by {@code key}.
  213. */
  214. public final V remove(K key) {
  215. if (key == null) {
  216. throw new NullPointerException("key == null");
  217. }
  218.  
  219. V previous;
  220. synchronized (this) {
  221. previous = map.remove(key);
  222. if (previous != null) {
  223. size -= safeSizeOf(key, previous);
  224. }
  225. }
  226.  
  227. if (previous != null) {
  228. entryRemoved(false, key, previous, null);
  229. }
  230.  
  231. return previous;
  232. }
  233.  
  234. /**
  235. * Called for entries that have been evicted or removed. This method is
  236. * invoked when a value is evicted to make space, removed by a call to
  237. * {@link #remove}, or replaced by a call to {@link #put}. The default
  238. * implementation does nothing.
  239. *
  240. * <p>The method is called without synchronization: other threads may
  241. * access the cache while this method is executing.
  242. *
  243. * @param evicted true if the entry is being removed to make space, false
  244. * if the removal was caused by a {@link #put} or {@link #remove}.
  245. * @param newValue the new value for {@code key}, if it exists. If non-null,
  246. * this removal was caused by a {@link #put}. Otherwise it was caused by
  247. * an eviction or a {@link #remove}.
  248. */
  249. protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {}
  250.  
  251. /**
  252. * Called after a cache miss to compute a value for the corresponding key.
  253. * Returns the computed value or null if no value can be computed. The
  254. * default implementation returns null.
  255. *
  256. * <p>The method is called without synchronization: other threads may
  257. * access the cache while this method is executing.
  258. *
  259. * <p>If a value for {@code key} exists in the cache when this method
  260. * returns, the created value will be released with {@link #entryRemoved}
  261. * and discarded. This can occur when multiple threads request the same key
  262. * at the same time (causing multiple values to be created), or when one
  263. * thread calls {@link #put} while another is creating a value for the same
  264. * key.
  265. */
  266. protected V create(K key) {
  267. return null;
  268. }
  269.  
  270. private int safeSizeOf(K key, V value) {
  271. int result = sizeOf(key, value);
  272. if (result < 0) {
  273. throw new IllegalStateException("Negative size: " + key + "=" + value);
  274. }
  275. return result;
  276. }
  277.  
  278. /**
  279. * Returns the size of the entry for {@code key} and {@code value} in
  280. * user-defined units. The default implementation returns 1 so that size
  281. * is the number of entries and max size is the maximum number of entries.
  282. *
  283. * <p>An entry's size must not change while it is in the cache.
  284. */
  285. protected int sizeOf(K key, V value) {
  286. return 1;
  287. }
  288.  
  289. /**
  290. * Clear the cache, calling {@link #entryRemoved} on each removed entry.
  291. */
  292. public final void evictAll() {
  293. trimToSize(-1); // -1 will evict 0-sized elements
  294. }
  295.  
  296. /**
  297. * For caches that do not override {@link #sizeOf}, this returns the number
  298. * of entries in the cache. For all other caches, this returns the sum of
  299. * the sizes of the entries in this cache.
  300. */
  301. public synchronized final int size() {
  302. return size;
  303. }
  304.  
  305. /**
  306. * For caches that do not override {@link #sizeOf}, this returns the maximum
  307. * number of entries in the cache. For all other caches, this returns the
  308. * maximum sum of the sizes of the entries in this cache.
  309. */
  310. public synchronized final int maxSize() {
  311. return maxSize;
  312. }
  313.  
  314. /**
  315. * Returns the number of times {@link #get} returned a value that was
  316. * already present in the cache.
  317. */
  318. public synchronized final int hitCount() {
  319. return hitCount;
  320. }
  321.  
  322. /**
  323. * Returns the number of times {@link #get} returned null or required a new
  324. * value to be created.
  325. */
  326. public synchronized final int missCount() {
  327. return missCount;
  328. }
  329.  
  330. /**
  331. * Returns the number of times {@link #create(Object)} returned a value.
  332. */
  333. public synchronized final int createCount() {
  334. return createCount;
  335. }
  336.  
  337. /**
  338. * Returns the number of times {@link #put} was called.
  339. */
  340. public synchronized final int putCount() {
  341. return putCount;
  342. }
  343.  
  344. /**
  345. * Returns the number of values that have been evicted.
  346. */
  347. public synchronized final int evictionCount() {
  348. return evictionCount;
  349. }
  350.  
  351. /**
  352. * Returns a copy of the current contents of the cache, ordered from least
  353. * recently accessed to most recently accessed.
  354. */
  355. public synchronized final Map<K, V> snapshot() {
  356. return new LinkedHashMap<K, V>(map);
  357. }
  358.  
  359. @Override public synchronized final String toString() {
  360. int accesses = hitCount + missCount;
  361. int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0;
  362. return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]",
  363. maxSize, hitCount, missCount, hitPercent);
  364. }
  365. }

Android LRUCache的更多相关文章

  1. Android LRUCache简介

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

  2. Android LruCache(Picasso内存缓存)

    Cache保存一个强引用来限制内容数量,每当Item被访问的时候,此Item就会移动到队列的头部,当cache已满的时候加入新的item时,在队列尾部的item会被回收. 如果你cache的某个值需要 ...

  3. 【转】Android LruCache源码介绍

    本文来源:转载自: http://blog.csdn.net/linghu_java/article/details/8574102 package android.util; import java ...

  4. Android LruCache究竟是什么

    源码: /frameworks/base/core/java/android/util/LruCache.java 文件开篇注释如下: A cache that holds strong refere ...

  5. Android LruCache技术原理

    概述 记得在很早之前,我有写过一篇文章Android高效加载大图.多图解决方案,有效避免程序OOM,这篇文章是翻译自Android Doc的,其中防止多图OOM的核心解决思路就是使用LruCache技 ...

  6. Android LruCache 压缩图片 有效避免程序OOM

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9316683 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工, ...

  7. Android——LruCache源码解析

    以下针对 Android API 26 版本的源码进行分析. 在了解LruCache之前,最好对LinkedHashMap有初步的了解,LruCache的实现主要借助LinkedHashMap.Lin ...

  8. Android LruCache源码简介

    package android.util; import java.util.LinkedHashMap; import java.util.Map; /** * A cache that holds ...

  9. Android lrucache 实现与使用(Android内存优化)

    什么是LruCache? LruCache实现原理是什么? 这两个问题其实可以作为一个问题来回答,知道了什么是 LruCache,就只然而然的知道 LruCache 的实现原理:Lru的全称是Leas ...

随机推荐

  1. jspxcms笔记三

    首页 index.html site :站点对象栏目 cover.html list.html node :栏目对象, text :正文详细 info.html node :栏目对象, info :文 ...

  2. 委托+内置委托方法+多播委托+lambda表达式+事件

    委托概念:如果我们要把方法当做参数来传递的话,就要用到委托.简单来说委托是一个类型,这个类型可以赋值一个方法的引用. 声明委托: 在C#中使用一个类分两个阶段,首选定义这个类,告诉编译器这个类由什么字 ...

  3. mindmanager思维导图软件

    Mindjet 由原名 Mindjet MindManager 简化而来,是倍受赞誉.最好的思维导图软件.所谓思维导图实际上就是一种将你的思想具体化,把你的思维分析整理为有计划有条理的导向图的工作管理 ...

  4. Oracle删除步骤

    1.Oracle卸载要求比较严格,不能简单的卸载就完事了:当然Oracle卸载也没有那么难,只是步骤比较多.Oracle10g还是Oracle11g卸载步骤都是一样的.下边详细介绍一下. 找到Orac ...

  5. hzau 1200 Choosy in Food

    1200: Choosy in Food Time Limit: 1 Sec  Memory Limit: 1280 MBSubmit: 32  Solved: 5[Submit][Status][W ...

  6. MySQL 大数据量修改表结构问题

    前言: 在系统正常运作一定时间后,随着市场.产品汪的需求不断变更,比较大的一些表结构面临不得不增加字段的方式来扩充满足业务需求:  而 MySQL 在体量上了千万.亿级别数据的时候,Alter Tab ...

  7. HANA 存储过程

    You can develop secure procedures using SQLScript in SAP HANA by observing the following recommendat ...

  8. Effective C++ 条款10

    令operator=返回一个reference to *this 将operator=返回一个reference是为了什么呢?答案很简单,就是为了实现连锁形式. 什么是连锁形式,如int x,y,z: ...

  9. CodeForces - 633H :Fibonacci-ish II(正解:莫对+线段树)

    Yash is finally tired of computing the length of the longest Fibonacci-ish sequence. He now plays ar ...

  10. ENTRYPOINT 与 CMD

    在Dockerfile中 ENTRYPOINT 只有最后一条生效,如果写了10条,前边九条都不生效 ENTRYPOINT 的定义为运行一个Docker容器像运行一个程序一样,就是一个执行的命令 两种写 ...