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 /** 56ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath * Sets the size of the cache. 57ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath * 58ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath * @param maxSize The new maximum size. 59ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath */ 60ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath public void resize(int maxSize) { 61ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath if (maxSize <= 0) { 62ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath throw new IllegalArgumentException("maxSize <= 0"); 63ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath } 64ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath 65ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath synchronized (this) { 66ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath this.maxSize = maxSize; 67ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath } 68ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath trimToSize(maxSize); 69ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath } 70ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath 71ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath /** 72795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the value for {@code key} if it exists in the cache or can be 73795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * created by {@code #create}. If a value was returned, it is moved to the 74795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * head of the queue. This returns null if a value is not cached and cannot 75795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * be created. 76795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 77a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson public final V get(K key) { 78795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson if (key == null) { 79795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson throw new NullPointerException("key == null"); 80795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 81795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 82a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson V mapValue; 83a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson synchronized (this) { 84a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson mapValue = map.get(key); 85a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson if (mapValue != null) { 86a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson hitCount++; 87a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson return mapValue; 88a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 89a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson missCount++; 90795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 91795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 92a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson /* 93a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * Attempt to create a value. This may take a long time, and the map 94a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * may be different when create() returns. If a conflicting value was 95a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * added to the map while create() was working, we leave that value in 96a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * the map and release the created value. 97a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson */ 98795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 99a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson V createdValue = create(key); 100a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson if (createdValue == null) { 101a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson return null; 102a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 103795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 104a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson synchronized (this) { 105795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson createCount++; 106a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson mapValue = map.put(key, createdValue); 107a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson 108a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson if (mapValue != null) { 109a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson // There was a conflict so undo that last put 110a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson map.put(key, mapValue); 111a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } else { 112a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson size += safeSizeOf(key, createdValue); 113a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 114a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 115a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson 116a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson if (mapValue != null) { 117a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson entryRemoved(false, key, createdValue, mapValue); 118a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson return mapValue; 119a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } else { 120795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson trimToSize(maxSize); 121a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson return createdValue; 122795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 123795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 124795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 125795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 126795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Caches {@code value} for {@code key}. The value is moved to the head of 127795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * the queue. 128795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * 129a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * @return the previous value mapped by {@code key}. 130795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 131a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson public final V put(K key, V value) { 132795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson if (key == null || value == null) { 133795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson throw new NullPointerException("key == null || value == null"); 134795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 135795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 136a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson V previous; 137a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson synchronized (this) { 138a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson putCount++; 139a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson size += safeSizeOf(key, value); 140a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson previous = map.put(key, value); 141a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson if (previous != null) { 142a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson size -= safeSizeOf(key, previous); 143a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 144a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 145a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson 146795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson if (previous != null) { 147a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson entryRemoved(false, key, previous, value); 148795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 149a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson 150795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson trimToSize(maxSize); 151795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return previous; 152795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 153795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 154a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson /** 155e00e7889dd8eb9389f7dff0f054e3e811b264a77Jeff Sharkey * Remove the eldest entries until the total of remaining entries is at or 156e00e7889dd8eb9389f7dff0f054e3e811b264a77Jeff Sharkey * below the requested size. 157e00e7889dd8eb9389f7dff0f054e3e811b264a77Jeff Sharkey * 158a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * @param maxSize the maximum size of the cache before returning. May be -1 159e00e7889dd8eb9389f7dff0f054e3e811b264a77Jeff Sharkey * to evict even 0-sized elements. 160a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson */ 161e00e7889dd8eb9389f7dff0f054e3e811b264a77Jeff Sharkey public void trimToSize(int maxSize) { 162a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson while (true) { 163a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson K key; 164a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson V value; 165a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson synchronized (this) { 166a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson if (size < 0 || (map.isEmpty() && size != 0)) { 167a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson throw new IllegalStateException(getClass().getName() 168a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson + ".sizeOf() is reporting inconsistent results!"); 169a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 170795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 1718e63c6994ea91c4a9ab3e68a60fcf6de7aab5565Jesse Wilson if (size <= maxSize || map.isEmpty()) { 172a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson break; 173a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 174a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson 1758e63c6994ea91c4a9ab3e68a60fcf6de7aab5565Jesse Wilson Map.Entry<K, V> toEvict = map.entrySet().iterator().next(); 176a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson key = toEvict.getKey(); 177a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson value = toEvict.getValue(); 178a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson map.remove(key); 179a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson size -= safeSizeOf(key, value); 180a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson evictionCount++; 181a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 182795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 183a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson entryRemoved(true, key, value, null); 184795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 185795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 186795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 187795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 188795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Removes the entry for {@code key} if it exists. 189795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * 190a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * @return the previous value mapped by {@code key}. 191795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 192a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson public final V remove(K key) { 193795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson if (key == null) { 194795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson throw new NullPointerException("key == null"); 195795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 196795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 197a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson V previous; 198a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson synchronized (this) { 199a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson previous = map.remove(key); 200a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson if (previous != null) { 201a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson size -= safeSizeOf(key, previous); 202a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 203a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson } 204a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson 205795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson if (previous != null) { 206a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson entryRemoved(false, key, previous, null); 207795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 208a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson 209795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return previous; 210795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 211795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 212795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 213a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * Called for entries that have been evicted or removed. This method is 214a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * invoked when a value is evicted to make space, removed by a call to 215a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * {@link #remove}, or replaced by a call to {@link #put}. The default 216a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * implementation does nothing. 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 * @param evicted true if the entry is being removed to make space, false 222a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * if the removal was caused by a {@link #put} or {@link #remove}. 223a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * @param newValue the new value for {@code key}, if it exists. If non-null, 224a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * this removal was caused by a {@link #put}. Otherwise it was caused by 225a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * an eviction or a {@link #remove}. 226795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 227a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {} 228795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 229795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 230795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Called after a cache miss to compute a value for the corresponding key. 231795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the computed value or null if no value can be computed. The 232795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * default implementation returns null. 233a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * 234a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * <p>The method is called without synchronization: other threads may 235a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * access the cache while this method is executing. 236a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * 237a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * <p>If a value for {@code key} exists in the cache when this method 238a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * returns, the created value will be released with {@link #entryRemoved} 239a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * and discarded. This can occur when multiple threads request the same key 240a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * at the same time (causing multiple values to be created), or when one 241a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * thread calls {@link #put} while another is creating a value for the same 242a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * key. 243795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 244795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson protected V create(K key) { 245795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return null; 246795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 247795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 248795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson private int safeSizeOf(K key, V value) { 249795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson int result = sizeOf(key, value); 250795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson if (result < 0) { 251795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson throw new IllegalStateException("Negative size: " + key + "=" + value); 252795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 253795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return result; 254795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 255795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 256795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 257795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the size of the entry for {@code key} and {@code value} in 258795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * user-defined units. The default implementation returns 1 so that size 259795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * is the number of entries and max size is the maximum number of entries. 260795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * 261795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * <p>An entry's size must not change while it is in the cache. 262795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 263795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson protected int sizeOf(K key, V value) { 264795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return 1; 265795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 266795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 267795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 268a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson * Clear the cache, calling {@link #entryRemoved} on each removed entry. 269795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 270a87be984a409450f8e697bd5009d2aa9ccebbea6Jesse Wilson public final void evictAll() { 271795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson trimToSize(-1); // -1 will evict 0-sized elements 272795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 273795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 274795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 275795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * For caches that do not override {@link #sizeOf}, this returns the number 276795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * of entries in the cache. For all other caches, this returns the sum of 277795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * the sizes of the entries in this cache. 278795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 279795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final int size() { 280795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return size; 281795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 282795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 283795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 284795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * For caches that do not override {@link #sizeOf}, this returns the maximum 285795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * number of entries in the cache. For all other caches, this returns the 286795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * maximum sum of the sizes of the entries in this cache. 287795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 288795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final int maxSize() { 289795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return maxSize; 290795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 291795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 292795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 293ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath * Returns the number of times {@link #get} returned a value that was 294ec04140e47f9253d6d25c5e0e5bb66b52c547ac7Narayan Kamath * already present in the cache. 295795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 296795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final int hitCount() { 297795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return hitCount; 298795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 299795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 300795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 301795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the number of times {@link #get} returned null or required a new 302795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * value to be created. 303795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 304795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final int missCount() { 305795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return missCount; 306795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 307795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 308795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 309795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the number of times {@link #create(Object)} returned a value. 310795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 311795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final int createCount() { 312795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return createCount; 313795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 314795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 315795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 316795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the number of times {@link #put} was called. 317795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 318795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final int putCount() { 319795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return putCount; 320795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 321795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 322795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 323795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns the number of values that have been evicted. 324795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 325795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final int evictionCount() { 326795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return evictionCount; 327795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 328795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 329795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson /** 330795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * Returns a copy of the current contents of the cache, ordered from least 331795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson * recently accessed to most recently accessed. 332795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson */ 333795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson public synchronized final Map<K, V> snapshot() { 334795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return new LinkedHashMap<K, V>(map); 335795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 336795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson 337795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson @Override public synchronized final String toString() { 338795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson int accesses = hitCount + missCount; 339795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0; 340795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]", 341795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson maxSize, hitCount, missCount, hitPercent); 342795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson } 343795b97d901e1793dac5c3e67d43c96a758fec388Jesse Wilson} 344