23. Реализовать `hashCode()` для класса Point
Условие задачи:
Дан класс Point с двумя полями: int x и int y.
Необходимо:
реализовать метод
hashCode();учитывать оба поля при вычислении хеша;
объяснить, какое значение возвращает
hashCode()и для чего оно используется.
Код:
public class Point {
private int x;
private int y;
// конструкторы, геттеры/сеттеры
@Override
public int hashCode() {
// TODO
}
}
Спойлеры к решению
Подсказки
hashCode() возвращает целое число типа int.💡 Если два объекта равны по
equals(), их hashCode() обязан быть одинаковым.💡 Для объединения нескольких полей часто используется множитель
31.💡 Если
equals() сравнивает x и y, эти же поля должны участвовать и в hashCode().Решение
public class Point {
private int x;
private int y;
@Override
public int hashCode() {
int result = 17;
result = 31 * result + x;
result = 31 * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Point)) {
return false;
}
Point other = (Point) obj;
return x == other.x
&& y == other.y;
}
}
hashCode() возвращает значение типа int, которое используется хеш-коллекциями, например HashMap и HashSet, для определения области, в которой следует искать объект.
В данном случае хеш рассчитывается по обоим полям:
int result = 17;
result = 31 * result + x;
result = 31 * result + y;
Главный контракт между equals() и hashCode():
a.equals(b) == true
↓
a.hashCode() == b.hashCode()
Обратное неверно: одинаковые хеш-коды не означают, что объекты обязательно равны. У разных объектов может возникнуть коллизия.
Например:
Point first = new Point(1, 2);
Point second = new Point(1, 2);
если equals() сравнивает координаты, то эти объекты равны и должны иметь одинаковый hashCode().
Также можно использовать более короткую запись:
@Override
public int hashCode() {
return Objects.hash(x, y);
}
Но ручная реализация хорошо показывает принцип вычисления хеша.
Важно: если объект используется как ключ в HashMap или хранится в HashSet, поля, участвующие в equals() и hashCode(), нежелательно изменять после добавления объекта в коллекцию. Иначе объект может оказаться в неправильной хеш-корзине и перестать корректно находиться.