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 <T> The type of the keys.
* @param <Y> The type of the values.
*/
public class LruCache<T, Y> {
private final LinkedHashMap<T, Y> cache = new LinkedHashMap<T, Y>(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(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(item);
return null;
}
currentSize += getSize(item);
final Y result = cache.put(key, item);
evict();
return result;
}
public void clearMemory() {
trimToSize(0);
}
protected void trimToSize(int size) {
Map.Entry<T, Y> last;
while (currentSize > size) {
last = cache.entrySet().iterator().next();
final Y toRemove = last.getValue();
currentSize -= getSize(toRemove);
cache.remove(last.getKey());
onItemRemoved(toRemove);
}
}
private void evict() {
trimToSize(maxSize);
}
}