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缓冲区,维护有限个值的强引用。当一个值被命中时,它被移到队列的头部???确定有移动么
当一个值被加入一个已满的cache中时,队列最后一个值被舍弃。可能会被垃圾回收
* <p>If your cached values hold resources that need to be explicitly released,- * override {@link #entryRemoved}.
如果你缓存的值中有必须被释放的资源,需要override 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.
如果一次cache未命中时,同样需要返回。 需要override create()方法。
这使调用简化:不管是不是命中,都返回一个值。- 因为当前的create方法返回的是个null。当你没get到的时候,会调用create方法。在当前情况下,返回null会直接return null。
不会往后执行之后的创建键值对,并返回的操作。- 但是如果你重写了create(),使其返回的不是null,则后边的操作会执行。调用get(key),value值被返回。
* <p>By default, the cache size is measured in the number of entries. Override- * {@link #sizeOf} to size the cache in different units. For example, this cache
- * is limited to 4MiB of bitmaps:
默认情况下,一个cache的大小,是以实体的个数来衡量的。因为当前的sizeOf() 方法返回的是1,也就是每个entry大小是1
你可以override sizeof方法,改变cache 的最小单元大小。
例如,下边这个cache 限制为最大4MiB的bitmap cache
每个单元的大小就不是1了,而是bitmap的大小。- * <pre> {@code
- * int cacheSize = 4 * 1024 * 1024; // 4MiB
- * LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) {
- * protected int sizeOf(String key, Bitmap value) {
- * return value.getByteCount();
- * }
- * }}</pre>
LRUCache类是线程安全的。多个cache操作时候。要synchronize这个cache- * <p>This class is thread-safe. Perform multiple cache operations atomically by
- * synchronizing on the cache: <pre> {@code
- * synchronized (cache) {
- * if (cache.get(key) == null) {
- * cache.put(key, value);
- * }
- * }}</pre>
这个类不允许传入的key和value是空。
get put remove返回null,代表这个key不再cache中- * <p>This class does not allow null to be used as a key or value. A return
- * value of null from {@link #get}, {@link #put} or {@link #remove} is
- * unambiguous: the key was not in the cache.
- *
- * <p>This class appeared in Android 3.1 (Honeycomb MR1); it's available as part
- * of <a href="http://developer.android.com/sdk/compatibility-library.html">Android's
- * Support Package</a> for earlier releases.
- */
- public class LruCache<K, V> {
- private final LinkedHashMap<K, V> map;
- /** Size of this cache in units. Not necessarily the number of elements. */
- private int size;
- private int maxSize;
- private int putCount;
- private int createCount;
- private int evictionCount;
- private int hitCount;
- private int missCount;
- /**
- * @param maxSize for caches that do not override {@link #sizeOf}, this is
- * the maximum number of entries in the cache. For all other caches,
- * this is the maximum sum of the sizes of the entries in this cache.
- */
- public LruCache(int maxSize) {
- if (maxSize <= 0) {
- throw new IllegalArgumentException("maxSize <= 0");
- }
- this.maxSize = maxSize;
- this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
- }
- /**
- * Sets the size of the cache.
- * @param maxSize The new maximum size.
- *
- * @hide
- */
- public void resize(int maxSize) {
- if (maxSize <= 0) {
- throw new IllegalArgumentException("maxSize <= 0");
- }
- synchronized (this) {
- this.maxSize = maxSize;
- }
- trimToSize(maxSize);
- }
- /**
- * Returns the value for {@code key} if it exists in the cache or can be
- * created by {@code #create}. If a value was returned, it is moved to the
- * head of the queue. This returns null if a value is not cached and cannot
- * be created.
- */
- 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++;
- }
- /*
- * Attempt to create a value. This may take a long time, and the map
- * may be different when create() returns. If a conflicting value was
- * added to the map while create() was working, we leave that value in
- * the map and release the created value.
- */
- 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
- map.put(key, mapValue);
- } else {
- size += safeSizeOf(key, createdValue);
- }
- }
- if (mapValue != null) {
- entryRemoved(false, key, createdValue, mapValue);
- return mapValue;
- } else {
- trimToSize(maxSize);
- return createdValue;
- }
- }
- /**
- * Caches {@code value} for {@code key}. The value is moved to the head of
- * the queue.
- *
- * @return the previous value mapped by {@code key}.
- */
- 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) {
- size -= safeSizeOf(key, previous);
- }
- }
- if (previous != null) {
- entryRemoved(false, key, previous, value);
- }
- trimToSize(maxSize);
- return previous;
- }
- /**
- * Remove the eldest entries until the total of remaining entries is at or
- * below the requested size.
- *
- * @param maxSize the maximum size of the cache before returning. May be -1
- * to evict even 0-sized elements.
- */
- public void trimToSize(int maxSize) {
- while (true) {
- K key;
- V value;
- synchronized (this) {
- if (size < 0 || (map.isEmpty() && size != 0)) {
- throw new IllegalStateException(getClass().getName()
- + ".sizeOf() is reporting inconsistent results!");
- }
- if (size <= maxSize) {
- break;
- }
- Map.Entry<K, V> toEvict = map.eldest();
- if (toEvict == null) {
- break;
- }
- key = toEvict.getKey();
- value = toEvict.getValue();
- map.remove(key);
- size -= safeSizeOf(key, value);
- evictionCount++;
- }
- entryRemoved(true, key, value, null);
- }
- }
- /**
- * Removes the entry for {@code key} if it exists.
- *
- * @return the previous value mapped by {@code key}.
- */
- 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;
- }
- /**
- * Called for entries that have been evicted or removed. This method is
- * invoked when a value is evicted to make space, removed by a call to
- * {@link #remove}, or replaced by a call to {@link #put}. The default
- * implementation does nothing.
- *
- * <p>The method is called without synchronization: other threads may
- * access the cache while this method is executing.
- *
- * @param evicted true if the entry is being removed to make space, false
- * if the removal was caused by a {@link #put} or {@link #remove}.
- * @param newValue the new value for {@code key}, if it exists. If non-null,
- * this removal was caused by a {@link #put}. Otherwise it was caused by
- * an eviction or a {@link #remove}.
- */
- protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {}
- /**
- * Called after a cache miss to compute a value for the corresponding key.
- * Returns the computed value or null if no value can be computed. The
- * default implementation returns null.
- *
- * <p>The method is called without synchronization: other threads may
- * access the cache while this method is executing.
- *
- * <p>If a value for {@code key} exists in the cache when this method
- * returns, the created value will be released with {@link #entryRemoved}
- * and discarded. This can occur when multiple threads request the same key
- * at the same time (causing multiple values to be created), or when one
- * thread calls {@link #put} while another is creating a value for the same
- * key.
- */
- protected V create(K key) {
- return null;
- }
- private int safeSizeOf(K key, V value) {
- int result = sizeOf(key, value);
- if (result < 0) {
- throw new IllegalStateException("Negative size: " + key + "=" + value);
- }
- return result;
- }
- /**
- * Returns the size of the entry for {@code key} and {@code value} in
- * user-defined units. The default implementation returns 1 so that size
- * is the number of entries and max size is the maximum number of entries.
- *
- * <p>An entry's size must not change while it is in the cache.
- */
- protected int sizeOf(K key, V value) {
- return 1;
- }
- /**
- * Clear the cache, calling {@link #entryRemoved} on each removed entry.
- */
- public final void evictAll() {
- trimToSize(-1); // -1 will evict 0-sized elements
- }
- /**
- * For caches that do not override {@link #sizeOf}, this returns the number
- * of entries in the cache. For all other caches, this returns the sum of
- * the sizes of the entries in this cache.
- */
- public synchronized final int size() {
- return size;
- }
- /**
- * For caches that do not override {@link #sizeOf}, this returns the maximum
- * number of entries in the cache. For all other caches, this returns the
- * maximum sum of the sizes of the entries in this cache.
- */
- public synchronized final int maxSize() {
- return maxSize;
- }
- /**
- * Returns the number of times {@link #get} returned a value that was
- * already present in the cache.
- */
- public synchronized final int hitCount() {
- return hitCount;
- }
- /**
- * Returns the number of times {@link #get} returned null or required a new
- * value to be created.
- */
- public synchronized final int missCount() {
- return missCount;
- }
- /**
- * Returns the number of times {@link #create(Object)} returned a value.
- */
- public synchronized final int createCount() {
- return createCount;
- }
- /**
- * Returns the number of times {@link #put} was called.
- */
- public synchronized final int putCount() {
- return putCount;
- }
- /**
- * Returns the number of values that have been evicted.
- */
- public synchronized final int evictionCount() {
- return evictionCount;
- }
- /**
- * Returns a copy of the current contents of the cache, ordered from least
- * recently accessed to most recently accessed.
- */
- public synchronized final Map<K, V> snapshot() {
- return new LinkedHashMap<K, V>(map);
- }
- @Override public synchronized final String toString() {
- int accesses = hitCount + missCount;
- int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0;
- return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]",
- maxSize, hitCount, missCount, hitPercent);
- }
- }
Android LRUCache的更多相关文章
- Android LRUCache简介
LRU Cache数据结构的介绍可以参考前面的http://www.cnblogs.com/XP-Lee/p/3441555.html. 本文以Android LRUCache来做一个简单的介绍.我们 ...
- Android LruCache(Picasso内存缓存)
Cache保存一个强引用来限制内容数量,每当Item被访问的时候,此Item就会移动到队列的头部,当cache已满的时候加入新的item时,在队列尾部的item会被回收. 如果你cache的某个值需要 ...
- 【转】Android LruCache源码介绍
本文来源:转载自: http://blog.csdn.net/linghu_java/article/details/8574102 package android.util; import java ...
- Android LruCache究竟是什么
源码: /frameworks/base/core/java/android/util/LruCache.java 文件开篇注释如下: A cache that holds strong refere ...
- Android LruCache技术原理
概述 记得在很早之前,我有写过一篇文章Android高效加载大图.多图解决方案,有效避免程序OOM,这篇文章是翻译自Android Doc的,其中防止多图OOM的核心解决思路就是使用LruCache技 ...
- Android LruCache 压缩图片 有效避免程序OOM
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9316683 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工, ...
- Android——LruCache源码解析
以下针对 Android API 26 版本的源码进行分析. 在了解LruCache之前,最好对LinkedHashMap有初步的了解,LruCache的实现主要借助LinkedHashMap.Lin ...
- Android LruCache源码简介
package android.util; import java.util.LinkedHashMap; import java.util.Map; /** * A cache that holds ...
- Android lrucache 实现与使用(Android内存优化)
什么是LruCache? LruCache实现原理是什么? 这两个问题其实可以作为一个问题来回答,知道了什么是 LruCache,就只然而然的知道 LruCache 的实现原理:Lru的全称是Leas ...
随机推荐
- jspxcms笔记三
首页 index.html site :站点对象栏目 cover.html list.html node :栏目对象, text :正文详细 info.html node :栏目对象, info :文 ...
- 委托+内置委托方法+多播委托+lambda表达式+事件
委托概念:如果我们要把方法当做参数来传递的话,就要用到委托.简单来说委托是一个类型,这个类型可以赋值一个方法的引用. 声明委托: 在C#中使用一个类分两个阶段,首选定义这个类,告诉编译器这个类由什么字 ...
- mindmanager思维导图软件
Mindjet 由原名 Mindjet MindManager 简化而来,是倍受赞誉.最好的思维导图软件.所谓思维导图实际上就是一种将你的思想具体化,把你的思维分析整理为有计划有条理的导向图的工作管理 ...
- Oracle删除步骤
1.Oracle卸载要求比较严格,不能简单的卸载就完事了:当然Oracle卸载也没有那么难,只是步骤比较多.Oracle10g还是Oracle11g卸载步骤都是一样的.下边详细介绍一下. 找到Orac ...
- hzau 1200 Choosy in Food
1200: Choosy in Food Time Limit: 1 Sec Memory Limit: 1280 MBSubmit: 32 Solved: 5[Submit][Status][W ...
- MySQL 大数据量修改表结构问题
前言: 在系统正常运作一定时间后,随着市场.产品汪的需求不断变更,比较大的一些表结构面临不得不增加字段的方式来扩充满足业务需求: 而 MySQL 在体量上了千万.亿级别数据的时候,Alter Tab ...
- HANA 存储过程
You can develop secure procedures using SQLScript in SAP HANA by observing the following recommendat ...
- Effective C++ 条款10
令operator=返回一个reference to *this 将operator=返回一个reference是为了什么呢?答案很简单,就是为了实现连锁形式. 什么是连锁形式,如int x,y,z: ...
- CodeForces - 633H :Fibonacci-ish II(正解:莫对+线段树)
Yash is finally tired of computing the length of the longest Fibonacci-ish sequence. He now plays ar ...
- ENTRYPOINT 与 CMD
在Dockerfile中 ENTRYPOINT 只有最后一条生效,如果写了10条,前边九条都不生效 ENTRYPOINT 的定义为运行一个Docker容器像运行一个程序一样,就是一个执行的命令 两种写 ...