package com.bumptech.glide.util; import java.util.LinkedHashMap; import java.util.Map; /** * A general purpose size limited cache that evicts items using an LRU algorithm. By default every item is assumed to * have a size of one. Subclasses can override {@link #getSize(Object)}} to change the size on a per item basis. * * @param The type of the keys. * @param The type of the values. */ public class LruCache { private final LinkedHashMap cache = new LinkedHashMap(100, 0.75f, true); private int maxSize; private final int initialMaxSize; private int currentSize = 0; public LruCache(int size) { this.initialMaxSize = size; this.maxSize = size; } public void setSizeMultiplier(float multiplier) { if (multiplier < 0) { throw new IllegalArgumentException("Multiplier must be >= 0"); } maxSize = Math.round(initialMaxSize * multiplier); evict(); } protected int getSize(Y item) { return 1; } protected void onItemRemoved(T key, Y item) { } public int getCurrentSize() { return currentSize; } public boolean contains(T key) { return cache.containsKey(key); } public Y get(T key) { return cache.get(key); } public Y put(T key, Y item) { final int itemSize = getSize(item); if (itemSize >= maxSize) { onItemRemoved(key, item); return null; } final Y result = cache.put(key, item); if (result != item) { currentSize += getSize(item); evict(); } return result; } public Y remove(T key) { final Y value = cache.remove(key); if (value != null) { currentSize -= getSize(value); } return value; } public void clearMemory() { trimToSize(0); } protected void trimToSize(int size) { Map.Entry last; while (currentSize > size) { last = cache.entrySet().iterator().next(); final Y toRemove = last.getValue(); currentSize -= getSize(toRemove); final T key = last.getKey(); cache.remove(key); onItemRemoved(key, toRemove); } } private void evict() { trimToSize(maxSize); } }