标签:android style blog color java os io strong
上一篇分析了LinkedHashMap源码,这个Map集合除了拥有HashMap的大部分特性之外,还拥有链表的特点,即可以保持遍历顺序与插入顺序一致。另外,当我们将accessOrder设置为true时,可以使遍历顺序和访问顺序一致,其内部双向链表将会按照近期最少访问到近期最多访问的顺序排列Entry对象,这可以用来做缓存。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;//put次数 private int createCount;//create次数 private int evictionCount;//回收次数 private int hitCount;//命中次数 private int missCount;//丢失次数LinkedHashMap的初始化放在构造器中:
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); }
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) {//之前已经插入过相同的key size -= safeSizeOf(key, previous);//那么减去该entry的容量,因为发生覆盖 } } if (previous != null) { entryRemoved(false, key, previous, value);//这个方法默认空实现 } trimToSize(maxSize);//若容量超过maxsize,将会删除最近很少访问的entry return previous; }
public void trimToSize(int maxSize) { while (true) {//不断删除linkedHashMap头部entry,也就是最近最少访问的条目,直到size小于最大容量 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 || map.isEmpty()) {//直到容量小于最大容量为止 break; } Map.Entry<K, V> toEvict = map.entrySet().iterator().next();//指向链表头 key = toEvict.getKey(); value = toEvict.getValue(); map.remove(key);//删除最少访问的entry size -= safeSizeOf(key, value); evictionCount++; } entryRemoved(true, key, value, null); } }
private 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 = null; for (Map.Entry<K, V> entry : map.entrySet()) { toEvict = entry; } if (toEvict == null) { break; } key = toEvict.getKey(); value = toEvict.getValue(); map.remove(key); size -= safeSizeOf(key, value); evictionCount++; } entryRemoved(true, key, value, null); } }
public final V get(K key) { if (key == null) {//不允许空键 throw new NullPointerException("key == null"); } V mapValue; synchronized (this) {//线程安全 mapValue = map.get(key);//调用LinkedHashMap的get方法 if (mapValue != null) { hitCount++;//命中次数加1 return mapValue;//返回value } missCount++;//未命中 } V createdValue = create(key);//默认返回为false if (createdValue == null) { return null; } synchronized (this) { createCount++;//如果创建成功,那么create次数加1 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; } }
public final V remove(K key) { if (key == null) { throw new NullPointerException("key == null"); } V previous; synchronized (this) { previous = map.remove(key);//调用LinkedHashMap的remove方法 if (previous != null) { size -= safeSizeOf(key, previous); } } if (previous != null) { entryRemoved(false, key, previous, null); } return previous;//返回value }
protected int sizeOf(K key, V value) {//用于计算每个条目的大小 return 1; }snapshot方法,返回当前缓存中所有的条目集合
public synchronized final Map<K, V> snapshot() { return new LinkedHashMap<K, V>(map); }
【源码】LruCache源码剖析,布布扣,bubuko.com
标签:android style blog color java os io strong
原文地址:http://blog.csdn.net/chdjj/article/details/38701509