Доступна ли какая-либо комбинация функций Cache
и Multimap
в Guava? По сути, мне нужна коллекция, срок действия записей которой истекает через заданное время, например доступное в Cache
, но у меня есть неуникальные ключи, и мне нужно, чтобы записи истекали независимо друг от друга.
Комбинация Java Guava Multimap и Cache
Ответы (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;
}
Это простое «решение» имеет некоторые ограничения, но мне оно подходит.
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;
Хитрость такого типа кеша заключается в том, что на самом деле ничего не истекает, пока кто-то его не запросит.
Cache
сам по себе не имеет метода put, и что LoadingCache
предназначен для самозаполнения, но вы всегда можете использовать незагружаемый кеш и вызывать cache.asMap().put(...)
для добавления своих собственных записей. Конечно, это не дает вам мультикарту. Просто исправляю первое утверждение.
- person Ray; 05.03.2012
Cache
. Предоставленный вами пример интересен, но я не могу полагаться на истечение срока действия запросов, я реализую RemovalListener
, чтобы получать уведомления об истечении срока действия в Cache
.
- person hgus1294; 05.03.2012
put
был добавлен в 11.0. Моя ошибка.
- person Ray; 05.03.2012
Multimap
чрезвычайно нетривиальны, а наши внутренние реализации не предназначены для обработки записей в кэше с истекающим сроком действия. Это был бы довольно крупный проект. знак равно
- person Louis Wasserman; 05.03.2012
Multimap
контракт. Серьезно.
- person Louis Wasserman; 06.03.2012
Пока вы говорите о Cache
, а не о LoadingCache
, вы можете передать представление Cache.asMap()
в Multimaps.newMultimap
.
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