最近被问到LruCache原理一直觉得很简单的东西猛然一想,卧槽忘了,赶紧翻开源码瞧瞧!
1、首先构造lrucache的时候会新建一个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); }
2、构造LinkedHashMap的时候传入了一个true作为accessOrder的值
public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) { super(initialCapacity, loadFactor); this.accessOrder = accessOrder; }
3、当LruCache调用get的时候会调用LinkedHashMap的方法
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++; 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; } }
4、这是LinkedHashMap的get方法
public V get(Object key) { Node<K,V> e; if ((e = getNode(key)) == null) return null; if (accessOrder) afterNodeAccess(e); return e.value; }
5、因为前面传入的accessOrder为true所以一定会调用afterNodeAccess方法
void afterNodeAccess(Node<K,V> e) { // move node to last LinkedHashMapEntry<K,V> last; if (accessOrder && (last = tail) != e) { LinkedHashMapEntry<K,V> p = (LinkedHashMapEntry<K,V>)e, b = p.before, a = p.after; p.after = null; if (b == null) head = a; else b.after = a; if (a != null) a.before = b; else last = b; if (last == null) head = p; else { p.before = last; last.after = p; } tail = p; ++modCount; } }
6、afterNodeAccess方法直接将被访问的元素放到了队列尾部并返回,然后lruCache进行重新trimtoSize的时候直接将移除的使map.eldest()返回的元素
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); } }
7、LinkedHashMap eldest()方法返回的直接是头节点,也就是最近使用的元素都会到LinkedHashMap的末尾节点,而头节点聚集的都是最久未使用元素
public Map.Entry<K, V> eldest() { return head; }
这就实现了缓存策略最近使用优先级最高
标签:map,解析,last,value,源码,mapValue,key,null,LruCache From: https://www.cnblogs.com/laogonggong/p/18164569