-
Notifications
You must be signed in to change notification settings - Fork 3
How to work with hashCode
Прежде всего, надо понимать, что hashCode наряду с equals играет важную роль в сравнении объектов. По сути он показывает изменилась ли информация, которую мы используем в equals для сравнения объектов.
Спецификация гласит:
- Метод hashCode должен вернуть одно и то же целое значение, если мы обратимся к одному и тому же объекту, если информация в объекте не поменялась.
- Если equals показывает, что два объекта равны - у таких объектов одинаковые hashCode.
- Если equals показывает, что объекты не равны, то НЕ обязательно у них разные hashCode.
Главное запомнить, что одинаковые объекты имеют одинаковый hashCode.
У Object-а:
public native int hashCode();
Именно поэтому, если вы переопределяете equals - вы обязаны переопределить hashCode.
Самый очевидный(и самый плохой) пример как переопределить hashCode - это всегда возвращать какое-то число.
@Override
public int hashCode() {
return 14;
}
Для равных объектов такой метод вернет одно и то же число, что удовлетворяет спецификации. Но таким образом мы будем сводить на нет все полезности hashmap, превращая их в связные списки.
Да и надо помнить, что хорошая функция hashCode - это гарантия быстродействия при работе с hashmap-ами.
При переопределении важно помнить, что необходимо исключить избыточные поля(которые не участвуют в equals). Также, если необходимо и ваш объект - неизменяемый, то hashCode можно закешировать.
Пример переопределения hashCode: //todo пример Как советует Блох переопределять hashCode: //todo пример
Правила Блоха:
- Присваиваем переменной result ненулевое значение.
- Далее для каждого значимого поля в объекте вычисляем hashCode:
- Если поле
boolean
-(f ? 1 : 0)
- Если поле
byte
,char
,short
илиint
-(int)f
- Если поле
long
-(int)(f ^ (f >>> 32))
- Если поле
float
, тоFloat.floatToIntBits(f);
- Если поле
double
, тоDouble.doubleToLongBits(f)
, а затем как сlong
. - Если поле это ссылка на другой объект, то рекурсивно вызовите
hashCode()
- Если поле
null
- то возвращаем 0. - Если поле это массив - то обрабатываем так, как будто каждый элемент массива - это поле объекта.
- Если поле
- После каждого обработанного поля объединяем его hashCode с текущим значением:
result = 31 * result + c; //c - это hashCode обработанного поля.
- Возвращаем результат.