码迷,mamicode.com
首页 > 移动开发 > 详细

Android LruCache类分析

时间:2017-06-19 12:56:34      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:创建   report   存储   linked   epo   trim   oev   form   creat   

public class LurCache<K, V> {
    private final LinkedHashMap<K, V> map;
    private int size; // 已经存储的大小
    private int maxSize; // 规定的最大存储空间
    private int putCount; // put的次数
    private int createCount; // create的次数
    private int evictionCount; // 回收的次数
    private int hitCount; // 命中的次数
    private int missCount; // 丢失的次数

    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 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++; // 丢失
        }

        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
                // 如果前面存在oldValue,那么撤销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 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) {  //返回的先前的value值
                size -= safeSizeOf(key, previous);  
            }  
        }  
  
        if (previous != null) {  
            entryRemoved(false, key, previous, value);  
        }  
  
        trimToSize(maxSize);  
        return previous;  
    }  
    //清空cache空间
    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 = map.entrySet().iterator().next();  
                if (toEvict == null) {  
                    break;  
                }  
  
                key = toEvict.getKey();  
                value = toEvict.getValue();  
                map.remove(key);  
                size -= safeSizeOf(key, value);  
                evictionCount++;  
            }  
  
            entryRemoved(true, key, value, null);  
        }  
    }  
    //删除key相应的cache项,返回相应的value
    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;  
    }  
    //当item被回收或者删掉时调用。该方法当value被回收释放存储空间时被remove调用, 或者替换item值时put调用,默认实现什么都没做。
    //true: 为释放空间被删除;false: put或remove导致
    protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {} 
    
    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;  
    }  
    
    protected int sizeOf(K key, V value) {  
        return 1;  
    }
    //清空cache
    public final void evictAll() {  
        trimToSize(-1); // -1 will evict 0-sized elements  
    }
    
    public synchronized final int size() {  
        return size;  
    }  
  
    public synchronized final int maxSize() {  
        return maxSize;  
    }  
  
    public synchronized final int hitCount() {  
        return hitCount;  
    }  
  
    public synchronized final int missCount() {  
        return missCount;  
    }  
  
    public synchronized final int createCount() {  
        return createCount;  
    }  
  
    public synchronized final int putCount() {  
        return putCount;  
    }  
  
    //返回被回收的数量
    public synchronized final int evictionCount() {  
        return evictionCount;  
    }  
    //返回当前cache的副本,从最近最少访问到最多访问
    public synchronized final Map<K, V> snapshot() {  
        return new LinkedHashMap<K, V>(map);  
    }  
  
    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类分析

标签:创建   report   存储   linked   epo   trim   oev   form   creat   

原文地址:http://www.cnblogs.com/zhujiabin/p/7047610.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!