Как правильно сгенерировать метод hashCode() для класса с полями id, age и email?

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

Ответ

Правильная генерация hashCode() критична для корректной работы коллекций, основанных на хэше (HashMap, HashSet). Метод должен соответствовать контракту: если два объекта равны по equals(), их hashCode() должен быть одинаковым.

Рекомендуемый способ (Java 7+): Использовать Objects.hash(), который эффективно обрабатывает null и массивы.

@Override
public int hashCode() {
    return Objects.hash(id, age, email); // Порядок аргументов важен!
}

Классическая ручная реализация (для понимания):

@Override
public int hashCode() {
    final int prime = 31; // Простое число для уменьшения коллизий
    int result = 1;
    result = prime * result + id;
    result = prime * result + age;
    result = prime * result + ((email == null) ? 0 : email.hashCode());
    return result;
}

Ключевые моменты:

  1. Используйте одни и те же поля, что и в equals().
  2. Порядок полей имеет значение для вычисления итогового хэша.
  3. Обрабатывайте null-поля (например, email).
  4. Для примитивов (int id, int age) используется их значение.
  5. Для ссылочных типов (String email) используется их собственный hashCode().

Почему 31? Это небольшое нечётное простое число. Умножение на него может быть оптимизировано компилятором как сдвиг и вычитание: 31 * i == (i << 5) - i.