zoukankan      html  css  js  c++  java
  • Android LruCache类分析

    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);  
        }  
    }
  • 相关阅读:
    IIS7.5应用程序池集成模式和经典模式的区别介绍(转)
    (转)Extjs4 展示图片与图片的更新
    webservices发布后远程无法调试的解决方法
    .Net通过OleDb方式读取Excel
    1000个JQuery插件(转载)
    2006年中科大计算机考研复试机试题
    2. 最好使用C++转型操作符
    16. 谨记8020法则
    英语阅读理解中表示作者态度的词汇汇总
    5. 对定制的“类型转换函数”保持警觉
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/7047610.html
Copyright © 2011-2022 走看看