Почему я должен переопределять hashCode (), когда я переопределяю метод equals ()?

Хорошо, я слышал из многих мест и источников, что всякий раз, когда я переопределяю метод equals (), мне нужно переопределить метод hashCode (). Но рассмотрим следующий fragment кода

package test; public class MyCustomObject { int intVal1; int intVal2; public MyCustomObject(int val1, int val2){ intVal1 = val1; intVal2 = val2; } public boolean equals(Object obj){ return (((MyCustomObject)obj).intVal1 == this.intVal1) && (((MyCustomObject)obj).intVal2 == this.intVal2); } public static void main(String a[]){ MyCustomObject m1 = new MyCustomObject(3,5); MyCustomObject m2 = new MyCustomObject(3,5); MyCustomObject m3 = new MyCustomObject(4,5); System.out.println(m1.equals(m2)); System.out.println(m1.equals(m3)); } } 

Здесь вывод true, false точно так, как я хочу, и мне не нужно переопределять метод hashCode (). Это означает, что hashCode () overriding является опцией, а скорее обязательной, как все говорят.

Я хочу получить второе подтверждение.

Он работает для вас, потому что ваш код не использует никаких функций (HashMap, HashTable), которым нужен API hashCode() .

Тем не менее, вы не знаете, будет ли ваш class (предположительно, не написанный как одноразовый) позже вызываться в коде, который действительно использует его объекты как hash-ключ, и в этом случае все будет затронуто.

Согласно документации для classа Object :

Общий контракт hashCode:

  • Всякий раз, когда он вызывается на одном и том же объекте более одного раза во время выполнения приложения Java, метод hashCode должен последовательно возвращать одно и то же целое число, если информация, используемая при равных сравнениях на объекте, не изменяется. Это целое число не должно оставаться согласованным с одним исполнением приложения на другое выполнение одного и того же приложения.

  • Если два объекта равны в соответствии с методом equals (Object), то вызов метода hashCode для каждого из двух объектов должен давать одинаковый целочисленный результат .

Поскольку HashMap / Hashtable будет искать объект с помощью hashCode ().

Если они не совпадают, hashmap будет утверждать, что объект не совпадает и возврат не существует на карте.

Причина, по которой вам нужно @Override ни или и другое, связано с тем, как они взаимосвязаны с остальной частью API.

Вы обнаружите, что если вы поместите m1 в HashSet , то он не contains(m2) . Это противоречивое поведение и может вызвать множество ошибок и хаоса.

Библиотека Java имеет множество функциональных возможностей. Чтобы заставить их работать на вас, вам нужно играть по правилам, и убедиться, что equals и hashCode являются совместимыми, является одним из самых важных.

Большинство других комментариев уже дали вам ответ: вам нужно сделать это, потому что есть коллекции (например, HashSet, HashMap), который использует hashCode как оптимизацию для «индексации» экземпляров объекта, эти оптимизации предполагают, что если: a.equals(b) ==> a.hashCode() == b.hashCode() ( a.hashCode() == b.hashCode() что инверсия не выполняется).

Но в качестве дополнительной информации вы можете сделать это упражнение:

 class Box { private String value; /* some boring setters and getters for value */ public int hashCode() { return value.hashCode(); } public boolean equals(Object obj) { if (obj != null && getClass().equals(obj.getClass()) { return ((Box) obj).value.equals(value); } else { return false; } } } 

Сделайте это:

 Set s = new HashSet(); Box b = new Box(); b.setValue("hello"); s.add(b); s.contains(b); // TRUE b.setValue("other"); s.contains(b); // FALSE s.iterator().next() == b // TRUE!!! b is in s but contains(b) returns false 

Что вы узнали из этого примера, так это то, что реализация equals или hashCode со свойствами, которые могут быть изменены (изменчивыми), является действительно плохой идеей.

Это в первую очередь важно при поиске объекта с использованием его значения hashCode () в коллекции (например, HashMap, HashSet и т. Д.). Каждый объект возвращает другое значение hashCode (), поэтому вы должны переопределить этот метод, чтобы последовательно генерировать значение hashCode на основе состояния объекта, чтобы помочь алгоритму Collections найти значения в хеш-таблице.

  • В чем разница между IEquatable и просто переопределением Object.Equals ()?
  • Любые причины, чтобы предпочесть getClass () над instanceof при генерации .equals ()?
  • В чем разница между «.equals» и «==»?
  • String.Equals () не работает по назначению
  • Какие проблемы следует учитывать при переопределении равных и hashCode в Java?
  • Как реализовать метод hashCode и equals
  • Сравнивая две строки, игнорируя регистр в c #
  • Переопределение GetHashCode для изменяемых объектов?
  • Использование '==' вместо .equals для строк Java
  • Как быстро проверить, имеют ли два объекта передачи данных равные свойства в C #?
  • Почему мне нужно переопределить методы equals и hashCode в Java?
  • Давайте будем гением компьютера.