¿Por qué debería anular hashCode () cuando anulo el método equals ()?

Ok, he escuchado de muchos lugares y fonts que siempre que sobreescribo el método equals (), también tengo que anular el método hashCode (). Pero considere la siguiente pieza de código

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)); } } 

Aquí la salida es verdadera, falsa exactamente como quiero que sea y no me importa anular el método hashCode (). Esto significa que la anulación de hashCode () es una opción más bien una obligatoria, como dicen todos.

Quiero una segunda confirmación.

Funciona para usted porque su código no utiliza ninguna funcionalidad (HashMap, HashTable) que necesita la API hashCode() .

Sin embargo, no se sabe si su clase (presumiblemente no escrita como única) se llamará más tarde en un código que sí utiliza sus objetos como clave hash, en cuyo caso las cosas se verán afectadas.

Según la documentación para la clase de objeto :

El contrato general de hashCode es:

  • Cada vez que se invoca en el mismo objeto más de una vez durante la ejecución de una aplicación Java, el método hashCode debe devolver el mismo entero de forma consistente, siempre que no se modifique la información utilizada en comparaciones iguales en el objeto. Este entero no necesita ser consistente desde una ejecución de una aplicación hasta otra ejecución de la misma aplicación.

  • Si dos objetos son iguales de acuerdo con el método equals (Object), entonces llamar al método hashCode en cada uno de los dos objetos debe producir el mismo resultado entero .

Porque HashMap / Hashtable buscará el objeto por hashCode () primero.

Si no son lo mismo, hashmap afirmará que el objeto no es el mismo y el retorno no existe en el mapa.

La razón por la cual necesita @Override o both, es debido a la forma en que se interrelacionan con el rest de la API.

Descubrirá que si coloca m1 en un HashSet , entonces no contains(m2) . Este es un comportamiento inconsistente y puede causar muchos errores y caos.

La biblioteca de Java tiene toneladas de funcionalidades. Para que funcionen para usted, debe cumplir con las reglas, y asegurarse de que equals y hashCode sean consistentes es uno de los más importantes.

La mayoría de los otros comentarios ya le dieron la respuesta: debe hacerlo porque hay colecciones (es decir: HashSet, HashMap) que usa hashCode como una optimización para “indexar” instancias de objetos, y esas optimizaciones esperan que si: a.equals(b) ==> a.hashCode() == b.hashCode() ( a.hashCode() == b.hashCode() CUENTA que el inverso no se mantiene).

Pero como información adicional puedes hacer este ejercicio:

 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; } } } 

El hacer esto:

 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 

Lo que se aprende de este ejemplo es que implementar equals o hashCode con propiedades que se pueden cambiar (mutable) es una idea realmente mala.

Es principalmente importante cuando se busca un objeto utilizando su valor hashCode () en una colección (es decir, HashMap, HashSet, etc.). Cada objeto devuelve un valor hashCode () diferente, por lo tanto, debe anular este método para generar consistentemente un valor hashCode basado en el estado del objeto para ayudar al algoritmo Collections a ubicar valores en la tabla hash.