2012-03-05 10 views
11

¿Existe alguna combinación de la funcionalidad de Cache y Multimap de Guava disponible? Básicamente, necesito una colección donde las entradas caducan después de un tiempo dado, como está disponible en Cache, pero tengo claves no únicas y necesito que las entradas caduquen de manera independiente.combinación de Java Guava de Multimap y Cache

Respuesta

4

Creo que Louis Wasserman proporcionó la respuesta en uno de los comentarios anteriores, es decir, que no hay disponible un combo de Multimap y Cache disponible. He resuelto mi problema/necesidades con la solución se describe en pseudo-código de abajo:

private Cache<Integer,Object> cache = CacheBuilder.newBuilder().SomeConfig.build(); 
private Multimap<Integer,Object> multimap = HashMultimap<Integer, Object>.create(); 
private AtomicInteger atomicid = new AtomicInteger(0); 

public void putInMultimap(int id, Object obj) { 
    int mapid = atomicid.addAndGet(1); 
    cache.put(mapid,obj); 
    multimap.put(id,mapid); 
} 
public List<Object> getFromMultimap(int id) { 
    Set<Integer> mapids = multimap.get(id); 
    List<Object> list = new ArrayList<Object>(); 
    for (int i : mapids) { 
     list.add(cache.getIfPresent(i)); 
    } 
    return list; 
} 

Esta 'solución' simple tiene algunas limitaciones pero funciona bien para mí.

+1

¿Cómo lidiar con el multimapa en constante crecimiento? – neu242

+1

@ neu242 para la parte 'SomeConfig' en la respuesta actual puede agregar una llamada' .removalListener', que se invocará cada vez que se expulse algo de la memoria caché, para que también pueda eliminarla del multimapa – Philipp

0

Con un caché de guayaba no hay poner el método, el caché está diseñado para ser auto-poblado. Los valores devueltos de una búsqueda de clave se calculan en tiempo de ejecución. Un enfoque similar es tomado por Commons Collections Transformer Factories.

Creo que podría implementar lo que está buscando con bastante facilidad. Si observa un ejemplo simple respaldado por un mapa, como Kitty-Cache, puede ver que puede reemplazar el mapa con un Multimap y reescribir los otros métodos en consecuencia. Así que en KittyCache.java internamente que podría tener algo como:

Multimap<K, CacheEntry<V>> cache; 

El truco para este tipo de caché es que en realidad nada ha caducado hasta que alguien lo solicite.

+3

"Con un caché de guayaba no hay un método put, el caché está diseñado para ser auto-poblado" - esto no es cierto. Es cierto que 'Cache' no tiene ningún método "put" y que 'LoadingCache' está diseñado para ser auto-poblado, pero siempre puedes usar un caché que no se carga y llamar a' cache.asMap(). Put (.. .) 'para agregar sus propias entradas. Por supuesto, esto no te da un multimap. Solo corrigiendo esa primera declaración. – Ray

+2

Desde Guava 11.0 hay un [método put] (http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/cache/Cache.html#put (K, V)) en 'Caché'. El ejemplo que proporcionó es interesante, pero no puedo confiar en la caducidad de las solicitudes, implemento 'RemovalListener' para recibir notificaciones sobre las caducidades en' Cache'. – hgus1294

+1

Gracias por poner esto en claro Ray. Estaba citando: http://java.dzone.com/articles/google-guava-cache –

0

Mientras que estás hablando y no CacheLoadingCache que podía pasar la vista Cache.asMap() en Multimaps.newMultimap.

+0

Interesante. Hice algunas pruebas, pero no puedo hacer que las entradas caduquen de forma independiente. Pasé un 'Cache.asMap()' en un 'Multimaps.newMultimap' según su sugerencia e hizo algunas pruebas rápidas con 'expireAfterWrite' establecido en 1000 ms y ejecutó el siguiente escenario: ' map.put (1, Object1); '' Thread.Sleep (700) '' map.put (1, Object2); '' Thread.Sleep (500) '. En este punto, espero que la primera entrada sea desalojada, pero la segunda permanezca pero encuentro que ambas entradas serán desalojadas. Tal vez estoy haciendo algo mal, pero a menos que pueda cambiar el comportamiento, no funciona para mí. – hgus1294

Cuestiones relacionadas