Как вычисляется метод hashCode() в Java и на основании каких данных?

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

Ответ

Метод hashCode() возвращает целочисленное значение (хэш-код), вычисляемое на основе внутреннего состояния объекта. Его цель — эффективная работа с хэш-коллекциями (HashMap, HashSet).

Стандартные реализации:

  • Примитивные обертки (Integer, Long): хэш-код равен значению.
  • String: вычисляется по полиномиальной формуле на основе всех символов строки.
  • Массивы: Arrays.hashCode() вычисляет хэш на основе элементов.
  • Объекты по умолчанию: Object.hashCode() часто возвращает преобразованный адрес в памяти.

Правила и контракт с equals():

  1. Если a.equals(b) == true, то a.hashCode() == b.hashCode() обязательно.
  2. Обратное не обязательно: одинаковые хэш-коды не гарантируют равенство объектов (коллизия).

Пример корректного переопределения hashCode() и equals():

public class Person {
    private final String name;
    private final int age;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        // Используем вспомогательный метод Objects.hash()
        return Objects.hash(name, age);
    }
}

Важно: Для изменяемых (mutable) полей, используемых в вычислении хэша, изменение поля после добавления объекта в HashSet или как ключа в HashMap приведет к невозможности его найти.