Ответ
Метод hashCode() возвращает целочисленное значение (хэш-код), вычисляемое на основе внутреннего состояния объекта. Его цель — эффективная работа с хэш-коллекциями (HashMap, HashSet).
Стандартные реализации:
- Примитивные обертки (
Integer,Long): хэш-код равен значению. - String: вычисляется по полиномиальной формуле на основе всех символов строки.
- Массивы:
Arrays.hashCode()вычисляет хэш на основе элементов. - Объекты по умолчанию:
Object.hashCode()часто возвращает преобразованный адрес в памяти.
Правила и контракт с equals():
- Если
a.equals(b) == true, тоa.hashCode() == b.hashCode()обязательно. - Обратное не обязательно: одинаковые хэш-коды не гарантируют равенство объектов (коллизия).
Пример корректного переопределения 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 приведет к невозможности его найти.
Ответ 18+ 🔞
Давай разберёмся с этим вашим hashCode(), а то народ путается, как последние идиоты. Ну, типа, представь, что у тебя есть объект, и ты хочешь его быстро находить в какой-нибудь коллекции, а не перебирать всё подряд, как конченый.
Что это вообще такое, этот хэш-код?
Это, блядь, просто число. Целое число. Вычисляется оно из того, что внутри объекта — из полей, грубо говоря. Главная задача — чтобы хэш-таблицы (эти твои HashMap, HashSet) работали быстро, а не ебались как кони с поиском.
Как его обычно получают, этот самый код?
- С примитивами (
Integer,Long) — вообще зашибись: хэш-код равен самому значению.Integer a = 42;— хэш тоже 42. Проще некуда. - Со строками (
String) — там уже умнее, формула такая полиномиальная, по всем символам бежит. Поэтому"пизда"и"пизда"дадут одинаковый хэш, а"пизда"и"писда"— уже разные, ёпта. - С массивами — тут надо
Arrays.hashCode()вызывать, он за тебя всё посчитает на основе элементов. Самому ебаться не надо. - А если ты свою херню написал (класс свой) и
hashCode()не переопределил — получишь дефолтную реализацию отObject. Она часто просто адрес в памяти как-то преобразует. И тогда даже два одинаковых, по твоей логике, объекта будут иметь разные хэши. И вHashMapты их не найдешь, будешь сидеть и ебать мозг, что за хуйня.
А теперь, сука, главное правило — контракт с equals()!
Запоминай раз и навсегда, чтобы потом не выть:
- Если
a.equals(b)вернулtrue(объекты равны по твоей бизнес-логике), то обязательно должно бытьa.hashCode() == b.hashCode(). Это железно. Нарушишь —HashMapиHashSetначнут глючить, как пьяный слесарь. - Обратное НЕ обязательно! Если хэши совпали — это ещё не значит, что объекты равны. Это называется коллизия, бывает. Хэш-таблицы с этим умеют жить.
Смотри, как это обычно делают, не выёбываясь:
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; // не null и того же класса
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name); // сравниваем поля
}
@Override
public int hashCode() {
// Идеально — использовать готовый `Objects.hash()`. Он сам там всё посчитает.
return Objects.hash(name, age);
}
}
И последнее, охуенно важное предупреждение!
Если ты используешь для хэша изменяемые поля (не final), и меняешь их после того, как засунул объект в HashSet или как ключ в HashMap — ты обречён. Объект ты уже не найдешь, потому что он будет искаться по старому хэшу, в другой корзине. Получится, что объект как бы есть, но его в упор не видно. Пиздец и карачун. Поэтому либо делай поля неизменяемыми, либо не используй их в hashCode(), либо будь готов к сюрпризам, хитрая жопа.