java caching lru

textarea java jframe



Caché LRU fácil de usar en java (5)

Sé que es fácil de implementar, pero quiero reutilizar algo que ya existe.

El problema que quiero resolver es que cargue la configuración (desde XML, así que quiero almacenarlos en la memoria caché) para diferentes páginas, roles, ... por lo que la combinación de entradas puede crecer bastante (pero en el 99% no). Para manejar este 1%, quiero tener un número máximo de elementos en el caché ...

Hasta ahora sé que encontré org.apache.commons.collections.map.LRUMap en apache commons y se ve bien, pero también quiero comprobar algo más. ¿Alguna recomendación?


Aquí está mi implementación que me permite mantener una cantidad óptima de elementos en la memoria.

El punto es que no necesito hacer un seguimiento de qué objetos están siendo utilizados actualmente, ya que estoy usando una combinación de un LinkedHashMap para los objetos MRU y un WeakHashMap para los objetos LRU. Entonces, la capacidad de la memoria caché no es menor que el tamaño de MRU más lo que sea que el GC me permita conservar. Cuando los objetos se caen de la MRU van a la LRU mientras el GC los tenga.

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); } }


Esta es una vieja pregunta, pero para la posteridad quería enumerar ConcurrentLinkedHashMap , que es seguro para subprocesos, a diferencia de LRUMap . El uso es bastante fácil:

ConcurrentMap<K, V> cache = new ConcurrentLinkedHashMap.Builder<K, V>() .maximumWeightedCapacity(1000) .build();

Y la documentación tiene algunos buenos examples , por examples , cómo hacer que el caché LRU se base en el tamaño en lugar de en el número de elementos.


Puede usar un LinkedHashMap (Java 1.4+):

// Create cache final int MAX_ENTRIES = 100; Map cache = new LinkedHashMap(MAX_ENTRIES+1, .75F, true) { // This method is called just after a new entry has been added public boolean removeEldestEntry(Map.Entry eldest) { return size() > MAX_ENTRIES; } }; // Add to cache Object key = "key"; cache.put(key, object); // Get object Object o = cache.get(key); if (o == null && !cache.containsKey(key)) { // Object not in cache. If null is not a possible value in the cache, // the call to cache.contains(key) is not needed } // If the cache is to be used by multiple threads, // the cache must be wrapped with code to synchronize the methods cache = (Map)Collections.synchronizedMap(cache);


También tuve el mismo problema y no encontré ninguna buena biblioteca ... así que creé la mía.

simplelrucache proporciona almacenamiento en caché LRU no distribuido, muy sencillo y no distribuido con soporte TTL. Proporciona dos implementaciones

  • Concurrente basado en ConcurrentLinkedHashMap
  • Sincronizado basado en LinkedHashMap

Puedes encontrarlo here .


Here hay una caché LRU muy simple y fácil de usar en Java. Aunque es corto y simple, es calidad de producción. El código es explicado (mira el archivo README.md) y tiene algunas pruebas unitarias.