LruCache源码解析

LruCache 内部相当于维护了一个LinkedHashMap

/**
* @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(0, 0.75f, true);
}

LinkedHashMap 结构为一个双向链表,对照看一下他的构造函数

//双向链表中元素排序规则的标志位。  
//accessOrder为false,表示按插入顺序排序  
//accessOrder为true,表示按访问顺序排序  
private final boolean accessOrder;  

//调用HashMap的构造方法来构造底层的数组  
public LinkedHashMap(int initialCapacity, float loadFactor) {  
   super(initialCapacity, loadFactor);  
   accessOrder = false;    //链表中的元素默认按照插入顺序排序  
 }  

//覆写HashMap中的get方法,通过getEntry方法获取Entry对象。  
//注意这里的recordAccess方法,  
//如果链表中元素的排序规则是按照插入的先后顺序排序的话,该方法什么也不做,  
//如果链表中元素的排序规则是按照访问的先后顺序排序的话,则将e移到链表的末尾处。  
public V get(Object key) {  
     Entry e = (Entry)getEntry(key);  
     if (e == null)  
          return null;  
     e.recordAccess(this);  
     return e.value;  
}  
  
//覆写HashMap中的recordAccess方法(HashMap中该方法为空),  
//当调用父类的put方法,在发现插入的key已经存在时,会调用该方法,  
//调用LinkedHashmap覆写的get方法时,也会调用到该方法,  
//该方法提供了LRU算法的实现,它将最近使用的Entry放到双向循环链表的尾部,  
//accessOrder为true时,get方法会调用recordAccess方法  
//put方法在覆盖key-value对时也会调用recordAccess方法  
//它们导致Entry最近使用,因此将其移到双向链表的末尾  
void recordAccess(HashMap m) {  
    LinkedHashMap lm = (LinkedHashMap)m;  
//如果链表中元素按照访问顺序排序,则将当前访问的Entry移到双向循环链表的尾部,  
//如果是按照插入的先后顺序排序,则不做任何事情。  
    if (lm.accessOrder) {  
        lm.modCount++;  
        //移除当前访问的Entry  
        remove();  
        //将当前访问的Entry插入到链表的尾部  
        addBefore(lm.header);  
       }  
}  

//双向循环立链表中,将当前的Entry插入到existingEntry的前面  
private void addBefore(Entry existingEntry) {  
            after  = existingEntry;  
            before = existingEntry.before;  
            before.after = this;  
            after.before = this;  
        }  
  

可以看到accessOrder参数决定LinkedHashMap以什么方式排序,当里面的节点被访问后,如果accessOrder为true他就会被移到头节点上面。来保持以访问顺序排序

你可能感兴趣的:(LruCache源码解析)