К каким проблемам приведет реализация hashCode(), возвращающая случайное число?

«К каким проблемам приведет реализация hashCode(), возвращающая случайное число?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Это грубое нарушение контракта hashCode() и сделает невозможной корректную работу hash-коллекций (HashMap, HashSet, Hashtable).

Контракт hashCode() требует:

  1. Консистентность: метод должен возвращать одно и то же целое число для неизмененного объекта.
  2. Согласованность с equals(): если a.equals(b) == true, то a.hashCode() == b.hashCode().

Последствия случайного hashCode():

  • Потеря объектов в коллекциях. Объект будет помещен в одну ячейку хэш-таблицы, но при поиске из-за другого хэш-кода будет просматриваться другая ячейка.
    Set<BadObject> set = new HashSet<>();
    BadObject obj = new BadObject(); // hashCode() возвращает random
    set.add(obj);
    System.out.println(set.contains(obj)); // С высокой вероятностью false
  • Нарушение инвариантов. HashSet может содержать дубликаты (объекты, для которых equals() возвращает true).
  • Катастрофическое падение производительности. Хэш-таблица превратится в связный список, так как все элементы будут иметь разные хэш-коды и могут попасть в одну корзину (bucket) из-за модульной операции, но поиск будет линейным.

Правильный подход: Хэш-код должен вычисляться на основе тех же полей, что участвуют в equals(), и быть детерминированным. Используйте Objects.hash() для удобства:

@Override
public int hashCode() {
    return Objects.hash(id, name); // Поля, используемые в equals()
}