Понимание содержит метод Java HashSet - PullRequest
14 голосов
/ 11 августа 2011

Вопрос новичка о java HashSet

Set<User> s = new HashSet<User>();
User u = new User();
u.setName("name1");
s.add(u);
u.setName("name3");
System.out.println(s.contains(u));

Может кто-нибудь объяснить, почему этот код выводит false?Более того, этот код даже не вызывает метод equals пользователя.Но, согласно источникам HashSet и HashMap, он должен вызывать его.Метод equals пользователя просто вызывает equals на имя пользователя.Метод hashCode возвращает hashCode имени пользователя

Ответы [ 2 ]

14 голосов
/ 11 августа 2011

Если метод хеш-кода основан на поле name, и вы затем измените его после добавления объекта, то вторая проверка contains будет использовать новое значение хеш-функции и не найдет объект, которым вы былинаходясь в поиске.Это потому, что HashSet первый поиск по хеш-коду, поэтому они не будут беспокоиться о вызове equals, если поиск не удастся.

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

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

10 голосов
/ 11 августа 2011

Поскольку ваш новый User имеет другой хеш-код, HashSet знает, что он не равен.

HashSets хранит свои элементы в соответствии со своими хеш-кодами.
HashSet будет вызывать только equalsесли он находит элемент с одинаковым хеш-кодом, чтобы убедиться, что два элемента фактически равны (в отличие от хеш-коллизии)

...