Какой самый лучший идентификатор при кэшировании множеств? Когда происходит вычисление hashCode набора? - PullRequest
1 голос
/ 07 июля 2011

Каков наилучший способ реализовать кеш для множеств? В частности, что делает лучший ключ для кэша?

В статическом методе фабрики я хочу включить механизм кэширования, чтобы я мог повторно использовать существующие (неизменяемые) объекты. Такое повторное использование не должно приводить к значительному снижению производительности. Критическими данными этого класса является параметризованный LinkedHashSet. Мне интересно, разумно ли использовать hashCode этого набора в качестве ключа для кэша (HashMap), потому что в документации по Java говорится: «Хеш-код набора определен как сумма хеш-кодов элементов в наборе». Разве это не медленный процесс? Когда рассчитывается? Как только Набор сформирован или по запросу? Разве это не может сильно снизить производительность, которую я ожидаю получить от кэширования?

Кроме того, hashCode - это int, но HashMaps не принимают примитивы, поэтому это включает в себя упаковку в Integer, верно?

Мой текущий подход заключается в том, чтобы поддерживать дополнительный набор длин наборов существующих объектов. Фабричный метод сначала проверит, указана ли длина текущего набора, и только затем просматривает фактический индекс. Но это также включает в себя бокс ...

Есть ли лучшее решение?

Ответы [ 2 ]

1 голос
/ 07 июля 2011

Не является ли это потенциально медленным процессом?Когда рассчитывается?Как только Набор сформирован или по запросу?Неужели это на самом деле не съедает прирост производительности, который я ожидаю получить от кэширования?

В принципе, это не указано в интерфейсе Set, поэтому оно зависит от реализации.

Для реализаций множеств общего назначения в java.util и java.util.concurrent (а также для представлений наборов карт общего назначения), hashCode() рассчитывается по требованию, а будет медленным для больших наборов .(Для небольших наборов с простыми элементами это на самом деле не имеет значения.)

Причина в том, что hashCode (а также equals), как определено, является динамическим, например, изменяется при добавлении элемента илиудаляется и изменяется также в случае изменения хэш-кода элемента (что само по себе проблематично для наборов на основе хеш-функции).Таким образом, обычно Set / List / Map на самом деле не является хорошим ключом для карты.

Для неизменяемого набора (который на практике также является единственным типом набора, который действительно подходит в качестве ключа карты),хеш-код может быть вычислен один раз (либо при создании, либо при первом использовании), а затем кэширован (как это делает String).

Можно также реализовать такое кэширование для изменяемых множеств, если хеш-кодыэлементы не меняются: формула достаточно проста, так что можно обновлять значение при каждом добавлении или удалении, не проверяя ничего, кроме добавленного / удаленного элемента.Но убедитесь, что набор не меняется, пока он используется в качестве ключа на карте.

(Большая часть этого также относится к списку и карте с их похожими формулами hashCode().)

1 голос
/ 07 июля 2011

Вам нужно использовать некоторый инвариант в качестве ключа для каждого набора, что-то, что логически определяет содержимое этого набора.

Подумайте о создании NamedSet, либо обернув существующую реализацию набора простым делегатором, либо создайте подклассы (если он не окончательный). Затем вы можете указать дополнительный ключ или поле имени для идентификации набора и использовать его в качестве ключа для своего кэша.

...