Сначала ответь вслух
Скажи ответ вслух хотя бы пару минут, потом открой эталон и сравни. Эталон открыт всем и не требует входа.
Показать ответ
Эталонный ответ
Контракт Object требует: если a.equals(b), то a.hashCode() == b.hashCode(). Реализация hashCode из Object от полей не зависит, поэтому два равных по смыслу объекта почти всегда получают разные хеши.
HashMap сначала выбирает корзину по хешу и только внутри корзины сравнивает ключи через equals. С разными хешами до equals дело не доходит: get вернёт null, а HashSet спокойно сохранит два «одинаковых» элемента.
record Point(int x, int y) {} // equals и hashCode по компонентам
class Pixel {
final int x, y;
Pixel(int x, int y) { this.x = x; this.y = y; }
@Override public boolean equals(Object o) {
return o instanceof Pixel p && p.x == x && p.y == y;
}
// hashCode не переопределён
}
Set<Pixel> set = new HashSet<>();
set.add(new Pixel(1, 2));
set.contains(new Pixel(1, 2)); // почти всегда falseОбратное не требуется: одинаковый хеш у разных объектов законен, это коллизия. Поэтому hashCode можно строить по части полей из equals, но нельзя по полям, которых в equals нет.
Как у тебя получилось?
Уточняющие вопросы
Так обычно копают глубже. Раскрой строку, когда ответишь вслух.
Уточнение 1-го уровня: Можно ли вернуть из hashCode константу?
Ответ уровня Junior
Контракт это не нарушает, но все ключи окажутся в одной корзине. Поиск деградирует: в списке корзины он линейный, а в дереве корзины (с Java 8) логарифмический, если ключи сравнимы.
Уточнение 2-го уровня: Когда корзина HashMap превращается в дерево?
Ответ уровня Middle
Когда в корзине становится больше 8 элементов (TREEIFY_THRESHOLD), а таблица не меньше 64 корзин. Если таблица меньше, HashMap сначала увеличивает её.
Уточнение 3-го уровня: А если ключи не реализуют Comparable?
Ответ уровня Senior
Дерево упорядочит их по хешу и служебному правилу разрешения ничьих, но при одинаковых хешах поиск обходит оба поддерева. В худшем случае он снова линейный.
Типичные ошибки
- Считать, что одинаковый hashCode означает равенство объектов: коллизии законны.
- Строить hashCode по полям, которые не участвуют в equals.
- Менять поля ключа после того, как он положен в HashMap.
Первоисточники
Быстрые задания по теме
Для темы «equals и hashCode» быстрых заданий пока нет
Можно проверить всю зону «Java Core» тестом на 10 минут.
Проверить себя за 10 минут