Комбинация Java Guava Multimap и Cache

Доступна ли какая-либо комбинация функций Cache и Multimap в Guava? По сути, мне нужна коллекция, срок действия записей которой истекает через заданное время, например доступное в Cache, но у меня есть неуникальные ключи, и мне нужно, чтобы записи истекали независимо друг от друга.


person hgus1294    schedule 05.03.2012    source источник


Ответы (3)


Я думаю, что Луи Вассерман дал ответ в одном из комментариев выше, то есть что нет готовой комбинации Multimap и Cache. Я решил свою проблему/требования с помощью решения, описанного в псевдокоде ниже:

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

Это простое «решение» имеет некоторые ограничения, но мне оно подходит.

person hgus1294    schedule 11.03.2012
comment
Как вы справляетесь с постоянно растущим числом карт? - person neu242; 26.05.2014
comment
@neu242 для части SomeConfig в текущем ответе вы можете добавить туда вызов .removalListener, который будет вызываться всякий раз, когда что-то удаляется из кеша, чтобы вы также могли удалить его из мультикарты. - person Philipp Gayret; 04.06.2014

В кэше Guava нет метода put, кэш предназначен для самозаполнения. Значения, возвращаемые при поиске ключа, вычисляются во время выполнения. Аналогичный подход используется компанией Commons Collections Transformer Factory.

Я думаю, вы могли бы легко реализовать то, что ищете. Если вы посмотрите на простой пример с поддержкой Map, такой как Kitty-Cache, вы увидите, что вы можете заменить Map на Multimap и соответствующим образом переписать другие методы. Итак, в KittyCache.java внутри у вас может быть что-то вроде:

Multimap<K, CacheEntry<V>> cache;

Хитрость такого типа кеша заключается в том, что на самом деле ничего не истекает, пока кто-то его не запросит.

person Mark McLaren    schedule 05.03.2012
comment
В Guava Cache нет метода put, кеш предназначен для самозаполнения — это неправда. Это правда, что Cache сам по себе не имеет метода put, и что LoadingCache предназначен для самозаполнения, но вы всегда можете использовать незагружаемый кеш и вызывать cache.asMap().put(...) для добавления своих собственных записей. Конечно, это не дает вам мультикарту. Просто исправляю первое утверждение. - person Ray; 05.03.2012
comment
Начиная с Guava 11.0 существует [метод put](docs.guava-libraries.googlecode.com/git/javadoc/com/google/, V)) в Cache. Предоставленный вами пример интересен, но я не могу полагаться на истечение срока действия запросов, я реализую RemovalListener, чтобы получать уведомления об истечении срока действия в Cache. - person hgus1294; 05.03.2012
comment
Спасибо за прямое изложение Рэя. Я цитировал: java.dzone.com/articles/google-guava-cache - person Mark McLaren; 05.03.2012
comment
Конечно, hgus1294 прав — put был добавлен в 11.0. Моя ошибка. - person Ray; 05.03.2012
comment
Марк, я полагаю, что статья была опубликована незадолго до выпуска 11.0, отсюда и путаница. - person Ray; 05.03.2012
comment
Для информации: Кэши, созданные с помощью CacheBuilder, не выполняют очистку и удаление значений автоматически или сразу после истечения срока действия значения или что-либо в этом роде. Вместо этого он выполняет небольшое обслуживание во время операций записи или во время случайных операций чтения, если записи происходят редко. См.: code.google.com/p/guava-libraries/wiki/ - person Mark McLaren; 05.03.2012
comment
Все это говорит о том, что реализации Multimap чрезвычайно нетривиальны, а наши внутренние реализации не предназначены для обработки записей в кэше с истекающим сроком действия. Это был бы довольно крупный проект. знак равно - person Louis Wasserman; 05.03.2012
comment
@LouisWasserman «Крупный проект», значит, не раньше конца месяца? Шучу, я ценю обратную связь, Луи. Спасибо - person hgus1294; 05.03.2012
comment
...Это может быть месячным проектом, чтобы получить что-то, что позволит правильно выполнить Multimap контракт. Серьезно. - person Louis Wasserman; 06.03.2012

Пока вы говорите о Cache, а не о LoadingCache, вы можете передать представление Cache.asMap() в Multimaps.newMultimap.

person fry    schedule 06.03.2012
comment
Интересно. Я провел некоторое тестирование, но не могу заставить записи истечь независимо. Я передал Cache.asMap() в Multimaps.newMultimap в соответствии с вашим предложением и провел быстрое тестирование с expireAfterWrite, установленным на 1000 мс, и выполнил следующий сценарий: map.put(1,Object1); Thread.Sleep(700) map.put(1,Object2); Thread.Sleep(500). В этот момент я ожидаю, что первая запись будет вытеснена, а вторая останется, но я нахожу, что обе записи будут вытеснены. Может быть, я делаю что-то не так, но если я не могу изменить поведение, это не работает для меня. - person hgus1294; 09.03.2012