La superclase de Java java.lang.Object
define dos métodos importantes:
public boolean equals(Object obj) public int hashCode() |
En esta publicación, primero mostraré un ejemplo de un error común y luego explicaré cómo contrato igual () y hashCode () obras.
1. Un error común
El error común se muestra en el siguiente ejemplo.
import java.util.HashMap; public class Apple { private String color; public Apple(String color) { this.color = color; } public boolean equals(Object obj) { if(obj==null) return false; if (!(obj instanceof Apple)) return false; if (obj == this) return true; return this.color.equals(((Apple) obj).color); } public static void main(String[] args) { Apple a1 = new Apple("green"); Apple a2 = new Apple("red"); //hashMap stores apple type and its quantity HashMap<Apple, Integer> m = new HashMap<Apple, Integer>(); m.put(a1, 10); m.put(a2, 20); System.out.println(m.get(new Apple("green"))); } } |
En el método principal, se crean dos manzanas («verde» y «roja») y se colocan en un HashMap. Sin embargo, cuando se le pide al mapa que proporcione la manzana verde, no se encuentra la manzana verde. El programa anterior imprime nulo. Estamos seguros de que la manzana verde se almacena en el hashMap al inspeccionar el HashMap en el depurador.
¿Qué causa el problema?
2. Problema causado por hashCode ()
El problema es causado por el método no reemplazado «hashCode ()». El contrato entre equals () y hashCode () es:
1) Si dos objetos son iguales, entonces deben tener el mismo código hash.
2) Si dos objetos tienen el mismo código hash, pueden ser iguales o no.
La idea detrás de un mapa es poder encontrar un objeto más rápido que una búsqueda lineal. El uso de claves hash para localizar objetos es un proceso de dos pasos. Internamente, HashMap se implementa como una matriz de objetos Entry. Cada entrada tiene un
La implementación predeterminada de hashCode () en la clase Object devuelve enteros distintos para diferentes objetos. Por tanto, la segunda manzana tiene un código hash diferente.
El HashMap está organizado como una secuencia de cubos. Los objetos clave se colocan en diferentes cubos. O (1) necesita tiempo para llegar al depósito correcto porque es un acceso a la matriz con el índice. Por lo tanto, es una buena práctica distribuir uniformemente los objetos en esos depósitos, es decir, tener un método hashCode () que produzca un código hash distribuido uniformemente. (Aunque no es el punto principal aquí)
La solución es agregar el método hashCode a la clase Apple. Aquí solo uso la longitud de la cadena de color para la demostración.
public int hashCode(){ return this.color.hashCode(); } |