1795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson/* 2795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Copyright (C) 2011 The Android Open Source Project 3795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * 4795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * you may not use this file except in compliance with the License. 6795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * You may obtain a copy of the License at 7795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * 8795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * 10795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * See the License for the specific language governing permissions and 14795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * limitations under the License. 15795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 16795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 17795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilsonpackage android.support.v4.util; 18795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 19795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilsonimport java.util.LinkedHashMap; 20795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilsonimport java.util.Map; 21795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 22795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson/** 237dc96cc2410f551eefaa973ddc144146ad72d1ecDianne Hackborn * Static library version of {@link android.util.LruCache}. Used to write apps 242f57cb1149f4ff23de0c8b926b893412704d3d35Jesse Wilson * that run on API levels prior to 12. When running on API level 12 or above, 252f57cb1149f4ff23de0c8b926b893412704d3d35Jesse Wilson * this implementation is still used; it does not try to switch to the 262f57cb1149f4ff23de0c8b926b893412704d3d35Jesse Wilson * framework's implementation. See the framework SDK documentation for a class 272f57cb1149f4ff23de0c8b926b893412704d3d35Jesse Wilson * overview. 28795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 29795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilsonpublic class LruCache<K, V> { 30795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson private final LinkedHashMap<K, V> map; 31795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 32795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** Size of this cache in units. Not necessarily the number of elements. */ 33795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson private int size; 34795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson private int maxSize; 35795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 36795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson private int putCount; 37795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson private int createCount; 38795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson private int evictionCount; 39795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson private int hitCount; 40795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson private int missCount; 41795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 42795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 43795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * @param maxSize for caches that do not override {@link #sizeOf}, this is 44795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * the maximum number of entries in the cache. For all other caches, 45795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * this is the maximum sum of the sizes of the entries in this cache. 46795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 47795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public LruCache(int maxSize) { 48795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson if (maxSize <= 0) { 49795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson throw new IllegalArgumentException("maxSize <= 0"); 50795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 51795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson this.maxSize = maxSize; 52795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson this.map = new LinkedHashMap<K, V>(0, 0.75f, true); 53795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 54795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 55795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 56795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the value for {@code key} if it exists in the cache or can be 57795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * created by {@code #create}. If a value was returned, it is moved to the 58795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * head of the queue. This returns null if a value is not cached and cannot 59795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * be created. 60795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 61a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson public final V get(K key) { 62795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson if (key == null) { 63795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson throw new NullPointerException("key == null"); 64795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 65795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 66a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson V mapValue; 67a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson synchronized (this) { 68a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson mapValue = map.get(key); 69a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson if (mapValue != null) { 70a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson hitCount++; 71a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson return mapValue; 72a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 73a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson missCount++; 74795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 75795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 76a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson /* 77a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * Attempt to create a value. This may take a long time, and the map 78a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * may be different when create() returns. If a conflicting value was 79a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * added to the map while create() was working, we leave that value in 80a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * the map and release the created value. 81a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson */ 82795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 83a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson V createdValue = create(key); 84a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson if (createdValue == null) { 85a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson return null; 86a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 87795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 88a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson synchronized (this) { 89795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson createCount++; 90a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson mapValue = map.put(key, createdValue); 91a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson 92a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson if (mapValue != null) { 93a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson // There was a conflict so undo that last put 94a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson map.put(key, mapValue); 95a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } else { 96a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson size += safeSizeOf(key, createdValue); 97a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 98a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 99a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson 100a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson if (mapValue != null) { 101a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson entryRemoved(false, key, createdValue, mapValue); 102a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson return mapValue; 103a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } else { 104795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson trimToSize(maxSize); 105a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson return createdValue; 106795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 107795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 108795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 109795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 110795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Caches {@code value} for {@code key}. The value is moved to the head of 111795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * the queue. 112795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * 113a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * @return the previous value mapped by {@code key}. 114795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 115a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson public final V put(K key, V value) { 116795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson if (key == null || value == null) { 117795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson throw new NullPointerException("key == null || value == null"); 118795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 119795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 120a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson V previous; 121a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson synchronized (this) { 122a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson putCount++; 123a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson size += safeSizeOf(key, value); 124a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson previous = map.put(key, value); 125a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson if (previous != null) { 126a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson size -= safeSizeOf(key, previous); 127a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 128a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 129a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson 130795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson if (previous != null) { 131a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson entryRemoved(false, key, previous, value); 132795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 133a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson 134795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson trimToSize(maxSize); 135795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return previous; 136795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 137795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 138a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson /** 139e00e7889dd8eb9389f7dff0f054e3e811b264a77Jeff Sharkey * Remove the eldest entries until the total of remaining entries is at or 140e00e7889dd8eb9389f7dff0f054e3e811b264a77Jeff Sharkey * below the requested size. 141e00e7889dd8eb9389f7dff0f054e3e811b264a77Jeff Sharkey * 142a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * @param maxSize the maximum size of the cache before returning. May be -1 143e00e7889dd8eb9389f7dff0f054e3e811b264a77Jeff Sharkey * to evict even 0-sized elements. 144a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson */ 145e00e7889dd8eb9389f7dff0f054e3e811b264a77Jeff Sharkey public void trimToSize(int maxSize) { 146a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson while (true) { 147a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson K key; 148a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson V value; 149a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson synchronized (this) { 150a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson if (size < 0 || (map.isEmpty() && size != 0)) { 151a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson throw new IllegalStateException(getClass().getName() 152a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson + ".sizeOf() is reporting inconsistent results!"); 153a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 154795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 1558e63c6994ea91c4a9ab3e68a60fcf6de7aab5565Jesse Wilson if (size <= maxSize || map.isEmpty()) { 156a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson break; 157a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 158a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson 1598e63c6994ea91c4a9ab3e68a60fcf6de7aab5565Jesse Wilson Map.Entry<K, V> toEvict = map.entrySet().iterator().next(); 160a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson key = toEvict.getKey(); 161a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson value = toEvict.getValue(); 162a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson map.remove(key); 163a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson size -= safeSizeOf(key, value); 164a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson evictionCount++; 165a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 166795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 167a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson entryRemoved(true, key, value, null); 168795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 169795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 170795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 171795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 172795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Removes the entry for {@code key} if it exists. 173795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * 174a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * @return the previous value mapped by {@code key}. 175795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 176a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson public final V remove(K key) { 177795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson if (key == null) { 178795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson throw new NullPointerException("key == null"); 179795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 180795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 181a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson V previous; 182a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson synchronized (this) { 183a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson previous = map.remove(key); 184a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson if (previous != null) { 185a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson size -= safeSizeOf(key, previous); 186a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 187a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 188a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson 189795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson if (previous != null) { 190a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson entryRemoved(false, key, previous, null); 191795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 192a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson 193795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return previous; 194795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 195795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 196795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 197a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * Called for entries that have been evicted or removed. This method is 198a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * invoked when a value is evicted to make space, removed by a call to 199a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * {@link #remove}, or replaced by a call to {@link #put}. The default 200a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * implementation does nothing. 201a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * 202a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * <p>The method is called without synchronization: other threads may 203a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * access the cache while this method is executing. 204a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * 205a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * @param evicted true if the entry is being removed to make space, false 206a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * if the removal was caused by a {@link #put} or {@link #remove}. 207a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * @param newValue the new value for {@code key}, if it exists. If non-null, 208a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * this removal was caused by a {@link #put}. Otherwise it was caused by 209a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * an eviction or a {@link #remove}. 210795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 211a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {} 212795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 213795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 214795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Called after a cache miss to compute a value for the corresponding key. 215795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the computed value or null if no value can be computed. The 216795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * default implementation returns null. 217a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * 218a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * <p>The method is called without synchronization: other threads may 219a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * access the cache while this method is executing. 220a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * 221a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * <p>If a value for {@code key} exists in the cache when this method 222a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * returns, the created value will be released with {@link #entryRemoved} 223a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * and discarded. This can occur when multiple threads request the same key 224a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * at the same time (causing multiple values to be created), or when one 225a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * thread calls {@link #put} while another is creating a value for the same 226a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * key. 227795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 228795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson protected V create(K key) { 229795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return null; 230795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 231795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 232795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson private int safeSizeOf(K key, V value) { 233795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson int result = sizeOf(key, value); 234795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson if (result < 0) { 235795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson throw new IllegalStateException("Negative size: " + key + "=" + value); 236795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 237795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return result; 238795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 239795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 240795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 241795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the size of the entry for {@code key} and {@code value} in 242795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * user-defined units. The default implementation returns 1 so that size 243795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * is the number of entries and max size is the maximum number of entries. 244795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * 245795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * <p>An entry's size must not change while it is in the cache. 246795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 247795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson protected int sizeOf(K key, V value) { 248795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return 1; 249795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 250795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 251795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 252a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * Clear the cache, calling {@link #entryRemoved} on each removed entry. 253795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 254a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson public final void evictAll() { 255795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson trimToSize(-1); // -1 will evict 0-sized elements 256795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 257795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 258795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 259795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * For caches that do not override {@link #sizeOf}, this returns the number 260795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * of entries in the cache. For all other caches, this returns the sum of 261795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * the sizes of the entries in this cache. 262795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 263795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final int size() { 264795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return size; 265795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 266795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 267795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 268795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * For caches that do not override {@link #sizeOf}, this returns the maximum 269795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * number of entries in the cache. For all other caches, this returns the 270795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * maximum sum of the sizes of the entries in this cache. 271795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 272795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final int maxSize() { 273795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return maxSize; 274795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 275795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 276795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 277795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the number of times {@link #get} returned a value. 278795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 279795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final int hitCount() { 280795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return hitCount; 281795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 282795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 283795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 284795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the number of times {@link #get} returned null or required a new 285795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * value to be created. 286795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 287795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final int missCount() { 288795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return missCount; 289795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 290795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 291795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 292795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the number of times {@link #create(Object)} returned a value. 293795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 294795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final int createCount() { 295795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return createCount; 296795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 297795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 298795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 299795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the number of times {@link #put} was called. 300795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 301795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final int putCount() { 302795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return putCount; 303795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 304795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 305795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 306795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the number of values that have been evicted. 307795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 308795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final int evictionCount() { 309795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return evictionCount; 310795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 311795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 312795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 313795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns a copy of the current contents of the cache, ordered from least 314795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * recently accessed to most recently accessed. 315795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 316795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final Map<K, V> snapshot() { 317795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return new LinkedHashMap<K, V>(map); 318795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 319795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 320795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson @Override public synchronized final String toString() { 321795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson int accesses = hitCount + missCount; 322795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0; 323795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]", 324795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson maxSize, hitCount, missCount, hitPercent); 325795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 326795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson} 327