equals и hashcode

Прежде чем пытаться понять методы equals() и hashCode(), необходимо вспомнить несколько фактов: в Java при сравнении ссылочных переменных сравниваются не сами объекты, а ссылки на объекты, и что все объекты унаследованы от класса Object, который содержит реализацию методов equals() и hashCode() по умолчанию.

Для решения задачи сравнения ссылочных переменных существует стандартное решение – метод equals(). Цель данного метода – определить идентичны ли объекты внутри, сравнив их внутреннее содержание. У класса Object есть своя реализация метода equals, которая просто сравнивает ссылки:


public boolean equals(Object var1) {

return this == var1;

}

Порой такой реализации бывает не достаточно, поэтому, при необходимости чтобы разные объекты с одинаковым содержимым рассматривались как равные, надо переопределить метод equals() учитывая поля, которые должны участвовать в сравнении объектов. Ведь только разработчик класса знает, какие данные важны, что учитывать при сравнении, а что – нет.

У метода equals() есть большой минус – он слишком медленно работает. Для этого был придуман метод hashCode(). Для каждого объекта данный метод возвращает определенное число. Какое именно – это тоже решает разработчик класса, как и в случае с методом equals().

Стандартная реализация метода hashCode() в классе Object:

public native int hashCode();

Вместо того чтобы сравнивать объекты, будем сравнивать их hashCode, и только если hashCode-ы равны, сравнивать объекты посредством equals().

Разработчик, который реализует функцию hashCode(), должен помнить следующее:

1) у двух разных объектов может быть одинаковый hashCode;

2) у одинаковых объектов (с точки зрения equals()должен быть одинаковый hashCode;

3) хеш-коды должны быть выбраны таким образом, чтобы не было большого количества различных объектов с одинаковыми hashCode. Ситуация, когда у различных объектов хеш-коды совпадают называется коллизией.

Важное замечание: при переопределении метода equals(), обязательно нужно переопределить метод hashCode(), с учетом трех вышеописанных правил (Переопределил equals — переопредели и hashCode).

Дело в том, что коллекции в Java перед тем как сравнить объекты с помощью equals всегда ищут/сравнивают их с помощью метода hashCode(). И если у одинаковых объектов будут разные hashCode, то объекты будут считаться разными — до сравнения с помощью equals() просто не дойдет.

Большинство современных IDE помогают переопределять методы equals() и hashCode(). К примеру, в Intellij Idea можно набрать комбинацию клавиш Alt+Ins, и в выпадающем меню Generate выбрать пункт equals and hashCode.