генерация кэш-ключа

Я использую ehcache (через плагин Grails). Метод, который добавляет объекты в кеш, требует, чтобы ключи были сериализуемыми, поэтому типичным использованием будет:

def key = 22
def someObject = new Object();
cacheService.cache(key, true, someObject)

(логический параметр указывает, следует ли добавить объект в распределенный или локальный кеш)

Мой вопрос в том, как мне генерировать ключи из объектов значений, таких как:

class Person implements Serializable {
  String firstName
  String lastName
  Integer age
}

Один из подходов — предоставить методы hashCode() и equals() и использовать hashCode в качестве ключа. В этом случае мне не нужно было бы реализовывать Serializable в классе Person.

В качестве альтернативы я мог бы просто использовать сам объект Person в качестве ключа. Похоже, мне все равно нужно будет предоставить методы equals и hashCode, но также нужно будет реализовать Serializable. Однако при таком подходе вероятность коллизий, по-видимому, меньше, потому что Person может быть равен только другому экземпляру Person.

Я предполагаю, что ehcache использует метод equals() ключа, чтобы определить, существует ли этот ключ в кеше. Верно ли это предположение?

Является ли один из подходов, описанных выше, лучше другого, или есть другой подход, который я не рассматривал?

Спасибо, Дон


person Dónal    schedule 10.09.2009    source источник


Ответы (1)


Ваш вопрос с хэш-ключом в основном ортогонален сериализуемому вопросу. В ответ на хеш-ключ я бы использовал Apache Commons HashCodeBuilder. Он делает всю тяжелую работу за вас. Аналогично с равными используйте метод EqualsBuilder.

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

Я бы не стал использовать объект Person в качестве ключа, так как он вызовет equals() для проверки сравнения ключей, что, вероятно, медленнее, чем сравнение целочисленного хэш-кода.

person Chris Kessel    schedule 10.09.2009
comment
Но также меньше шансов на коллизии, если я использую Person, потому что он может быть равен только другим экземплярам Person - person Dónal; 11.09.2009
comment
Во-первых, беспокойство об этом столкновении связано с предварительной оптимизацией. Помните правила оптимизации :). 1) Не оптимизируйте, 2) Пока не оптимизируйте. Во-вторых, вероятность того, что два объекта создадут один и тот же хэш, довольно мала. В-третьих, если вы собираетесь использовать Person в качестве ключа, вам все равно придется реализовать equals() hashcode(), ЕСЛИ вы не полагаетесь на фактическое равенство объектов (==) для поиска, а не на эквивалентность (equals()). - person Chris Kessel; 11.09.2009
comment
Столкновение = повреждение кеша. Коррупция = очень плохо. Очень плохо = нет оптимизации. Я ошеломлен тем, что многие люди, работающие с ehcache (и особенно разрабатывающие абстракцию кэша Spring), по-видимому, забыли, что hashCode(obj1)=hashCode(obj2) =\=> obj1=obj2. - person Peter Davis; 12.11.2011
comment
Коллизия хэш-кода не является повреждением. Вполне допустимо, что множество объектов имеют один и тот же хэш-код. Это ужасно неэффективно, поскольку HashMaps должны сохранять списки элементов для этого хеш-кода. Теперь не путайте хэш-код с фактическим поиском ключа карты, и в этом случае коллизия — это плохо. - person Chris Kessel; 24.11.2011