- 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类分析
最新推荐文章于 2024-04-30 08:14:34 发布