Кэширующая сетоподобная коллекция - PullRequest
2 голосов
/ 10 мая 2011

Я пытаюсь кэшировать множество похожих значений только с заданными требованиями. К сожалению, Set<?> позволяет мне только проверить, существует ли элемент внутри - он не вернет мне существующий элемент. То, что я хотел бы сделать, это:

Element e = receiveSomeElement();
e = elements.cache(e);
// now e is either the original e, or one that was already in the cache
doSomeWorkOn(e);

Я мог бы, вероятно, смоделировать это с SortedSet и получить .subSet(e, e), но кажется, что тратить время, чтобы сохранить сортировку в наборе Я мог бы также использовать HashMap<Element, Element> и хранить ту же ссылку, что и ключ и значение, но это выглядит так же грязно ...

Есть ли лучший способ сделать это?

Ответы [ 5 ]

3 голосов
/ 10 мая 2011

Если вы используете HashSet, базовая реализация в любом случае использует HashMap, поэтому я предлагаю вам использовать HashMap.

1 голос
/ 09 января 2012

Возможно, вы захотите взглянуть на LRUMap , предоставляемый Apache Collections.Он ведет себя как карта, но ограничивает размер, чтобы при обработке большого объема данных все не выходило из-под контроля.Я также написал статью о том, как добавить некоторые бухгалтерии в LRUMap, чтобы они также сокращались, когда не используются: Сообщение в блоге: Кэширование без сбоев

0 голосов
/ 10 мая 2011

Вот решение.Не утверждая, что я решил бы это так.Посмотрите, как демонстрация того, как получить определенный элемент в наборе.

// Create a temporary copy of the cache.
Set<Element> matches = new HashSet<Element>(cache);

// Remove all elements that don't equal the soughtElement.
matches.retainAll(Collections.singleton(soughtElement));

if (matches.isEmpty()) {
    // ... not found
} else {
    Element found = matches.iterator().next();
    // ...
}
0 голосов
/ 10 мая 2011

Возможно, вы захотите использовать LinkedHashMap, чтобы реализовать простую политику выселения.

Map<Element, Element> cache = new LinkedHashMap<Element, Element>(16, 0.7, true){
    protected boolean removeEldestEntry(Map.Entry<Element, Element> eldest) {
        return size() > MAX_SIZE;
    }

    public Element get(Object key) {
        Element element = super.get(key);
        // put if not present.
        if (element == null) {
            element = (Element) key;
            super.put(element, element)
        }
        return element;
    }
};

Таким образом, вы можете вызвать get (e), и он вернет e, если его нет. Он ограничен MAX_SIZE, удаляя наименее использованную запись, если требуется.

0 голосов
/ 10 мая 2011

ниже - базовая реализация кэширования, здесь также используется HashMap Реализация кэширования

...