19aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Juddpackage com.bumptech.glide.util; 29aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd 39aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Juddimport java.util.LinkedHashMap; 49aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Juddimport java.util.Map; 59aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd 69aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd/** 79aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd * A general purpose size limited cache that evicts items using an LRU algorithm. By default every item is assumed to 89aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd * have a size of one. Subclasses can override {@link #getSize(Object)}} to change the size on a per item basis. 99aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd * 109aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd * @param <T> The type of the keys. 119aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd * @param <Y> The type of the values. 129aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd */ 139aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Juddpublic class LruCache<T, Y> { 149aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd private final LinkedHashMap<T, Y> cache = new LinkedHashMap<T, Y>(100, 0.75f, true); 15d8900c3aa1844ac66a1019eefd368c83459c2c4cSam Judd private int maxSize; 16d8900c3aa1844ac66a1019eefd368c83459c2c4cSam Judd private final int initialMaxSize; 179aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd private int currentSize = 0; 189aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd 199aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd public LruCache(int size) { 20d8900c3aa1844ac66a1019eefd368c83459c2c4cSam Judd this.initialMaxSize = size; 219aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd this.maxSize = size; 229aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd } 239aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd 24d8900c3aa1844ac66a1019eefd368c83459c2c4cSam Judd public void setSizeMultiplier(float multiplier) { 25d8900c3aa1844ac66a1019eefd368c83459c2c4cSam Judd if (multiplier < 0) { 26d8900c3aa1844ac66a1019eefd368c83459c2c4cSam Judd throw new IllegalArgumentException("Multiplier must be >= 0"); 27d8900c3aa1844ac66a1019eefd368c83459c2c4cSam Judd } 28d8900c3aa1844ac66a1019eefd368c83459c2c4cSam Judd maxSize = Math.round(initialMaxSize * multiplier); 29d8900c3aa1844ac66a1019eefd368c83459c2c4cSam Judd evict(); 30d8900c3aa1844ac66a1019eefd368c83459c2c4cSam Judd } 31d8900c3aa1844ac66a1019eefd368c83459c2c4cSam Judd 329aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd protected int getSize(Y item) { 339aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd return 1; 349aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd } 359aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd 3678bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd protected void onItemRemoved(T key, Y item) { } 379aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd 389aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd public int getCurrentSize() { 399aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd return currentSize; 409aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd } 419aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd 429aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd public boolean contains(T key) { 439aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd return cache.containsKey(key); 449aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd } 459aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd 469aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd public Y get(T key) { 479aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd return cache.get(key); 489aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd } 499aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd 509aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd public Y put(T key, Y item) { 510e2e2b1b8df449b6e3223b090f5a55f1993e6c1fSam Judd final int itemSize = getSize(item); 520e2e2b1b8df449b6e3223b090f5a55f1993e6c1fSam Judd if (itemSize >= maxSize) { 5378bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd onItemRemoved(key, item); 540e2e2b1b8df449b6e3223b090f5a55f1993e6c1fSam Judd return null; 550e2e2b1b8df449b6e3223b090f5a55f1993e6c1fSam Judd } 560e2e2b1b8df449b6e3223b090f5a55f1993e6c1fSam Judd 579aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd final Y result = cache.put(key, item); 588ff32510d6572ca4952a87ccb8ad7140c1619443Sam Judd if (result != item) { 598ff32510d6572ca4952a87ccb8ad7140c1619443Sam Judd currentSize += getSize(item); 608ff32510d6572ca4952a87ccb8ad7140c1619443Sam Judd evict(); 618ff32510d6572ca4952a87ccb8ad7140c1619443Sam Judd } 629aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd return result; 639aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd } 649aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd 65e743a1f03f24e33270f38de883b508d4312a7f69Sam Judd public Y remove(T key) { 66e743a1f03f24e33270f38de883b508d4312a7f69Sam Judd final Y value = cache.remove(key); 67e743a1f03f24e33270f38de883b508d4312a7f69Sam Judd if (value != null) { 68e743a1f03f24e33270f38de883b508d4312a7f69Sam Judd currentSize -= getSize(value); 69e743a1f03f24e33270f38de883b508d4312a7f69Sam Judd } 70e743a1f03f24e33270f38de883b508d4312a7f69Sam Judd return value; 71e743a1f03f24e33270f38de883b508d4312a7f69Sam Judd } 72e743a1f03f24e33270f38de883b508d4312a7f69Sam Judd 739aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd public void clearMemory() { 749aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd trimToSize(0); 759aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd } 769aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd 779aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd protected void trimToSize(int size) { 789aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd Map.Entry<T, Y> last; 799aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd while (currentSize > size) { 809aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd last = cache.entrySet().iterator().next(); 819aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd final Y toRemove = last.getValue(); 829aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd currentSize -= getSize(toRemove); 8378bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd final T key = last.getKey(); 8478bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd cache.remove(key); 8578bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd onItemRemoved(key, toRemove); 869aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd } 879aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd } 889aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd 899aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd private void evict() { 909aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd trimToSize(maxSize); 919aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd } 929aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Judd} 93