Fácil, simples de usar cache LRU em java

Eu sei que é simples de implementar, mas quero reutilizar algo que já existe.

O problema que quero resolver é que eu carrego a configuração (do XML, então quero armazená-los em cache) para diferentes páginas, funções … para que a combinação de inputs possa crescer bastante (mas em 99% não). Para lidar com esse 1%, eu quero ter um número máximo de itens no cache …

Até saber que eu encontrei org.apache.commons.collections.map.LRUMap no apache commons e parece bem, mas quero verificar também outra coisa. Alguma recomendação?

    Você pode usar um 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); 

    Esta é uma pergunta antiga, mas para a posteridade eu queria listar ConcurrentLinkedHashMap , que é thread-safe, ao contrário do LRUMap . O uso é muito fácil:

     ConcurrentMap cache = new ConcurrentLinkedHashMap.Builder() .maximumWeightedCapacity(1000) .build(); 

    E a documentação tem alguns bons exemplos , como como fazer o LRU baseado em tamanho de cache em vez de número de itens baseado.

    Aqui está a minha implementação, que me permite manter um número ideal de elementos na memory.

    O ponto é que eu não preciso acompanhar quais objects estão sendo usados ​​atualmente desde que eu estou usando uma combinação de um LinkedHashMap para os objects MRU e um WeakHashMap para os objects LRU. Portanto, a capacidade do cache não é menor que o tamanho do MRU mais o que o GC me permite manter. Sempre que os objects caem do MRU, eles vão para o LRU pelo tempo que o GC os tiver.

     public class Cache { final Map MRUdata; final Map LRUdata; public Cache(final int capacity) { LRUdata = new WeakHashMap(); MRUdata = new LinkedHashMap(capacity+1, 1.0f, true) { protected boolean removeEldestEntry(Map.Entry 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); } } 

    Eu também tive o mesmo problema e não encontrei nenhuma boa biblioteca … então criei a minha própria.

    O simplelrucache fornece armazenamento em cache LRU thread-safe, muito simples e não distribuído com suporte a TTL. Ele fornece duas implementações

    • Concorrente baseado em ConcurrentLinkedHashMap
    • Sincronizado com base no LinkedHashMap

    Você pode encontrá-lo aqui .

    Aqui está um muito simples e fácil de usar o cache LRU em Java. Embora seja curto e simples, é a qualidade da produção. O código é explicado (veja o README.md) e tem alguns testes de unidade.