Вот моя реализация, которая позволяет мне хранить в памяти оптимальное количество элементов.
Дело в том, что мне не нужно отслеживать, какие объекты используются в настоящее время, поскольку я использую комбинацию LinkedHashMap для объектов MRU и WeakHashMap для объектов LRU.
Таким образом, емкость кеша не меньше размера MRU плюс все, что позволяет мне сохранить GC. Всякий раз, когда объекты падают с MRU, они отправляются в LRU до тех пор, пока GC будет иметь их.
public class Cache<K,V> {
final Map<K,V> MRUdata;
final Map<K,V> LRUdata;
public Cache(final int capacity)
{
LRUdata = new WeakHashMap<K, V>();
MRUdata = new LinkedHashMap<K, V>(capacity+1, 1.0f, true) {
protected boolean removeEldestEntry(Map.Entry<K,V> entry)
{
if (this.size() > capacity) {
LRUdata.put(entry.getKey(), entry.getValue());
return true;
}
return false;
};
};
}
public synchronized V tryGet(K key)
{
V value = MRUdata.get(key);
if (value!=null)
return value;
value = LRUdata.get(key);
if (value!=null) {
LRUdata.remove(key);
MRUdata.put(key, value);
}
return value;
}
public synchronized void set(K key, V value)
{
LRUdata.remove(key);
MRUdata.put(key, value);
}
}