El artículo trata sobre hashCode y es igual al contrato utilizado para el método contains (Object o) en Set.
Un acertijo sobre el uso del método contains () de Set
import java.util.HashSet; class Dog{ String color; public Dog(String s){ color = s; } } public class SetAndHashCode { public static void main(String[] args) { HashSet<Dog> dogSet = new HashSet<Dog>(); dogSet.add(new Dog("white")); dogSet.add(new Dog("white")); System.out.println("We have " + dogSet.size() + " white dogs!"); if(dogSet.contains(new Dog("white"))){ System.out.println("We have a white dog!"); }else{ System.out.println("No white dog!"); } } } |
Producción:
¡Tenemos 2 perros blancos!
¡Ningún perro blanco!
Agregamos dos perros blancos al set – dogSet, y el tamaño muestra que tenemos 2 perros blancos. Pero, ¿por qué no hay un perro blanco cuando usamos el método contains ()?
El método contiene (Objeto o) de Set
Desde Java Doc, el método contains () devuelve verdadero si y solo si este conjunto contiene un elemento e tal que (o == null? E == null: o.equals (e)). Entonces, el método contains () realmente usa el método equals () para verificar la igualdad.
Tenga en cuenta que nulo se puede agregar a un conjunto como elemento. El siguiente código realmente se imprime cierto.
HashSet<Dog> a = new HashSet<Dog>(); a.add(null); if(a.contains(null)){ System.out.println("true"); } |
La public boolean es igual a (Object obj) El método se define en la clase Object. Cada clase (incluidas las clases definidas por usted mismo) tiene Object como una superclase y es la raíz de cualquier jerarquía de clases. Todos los objetos, incluidas las matrices, implementan los métodos de esta clase.
En la clase definida por usted mismo, si no anula explícitamente este método, tendrá una implementación predeterminada. Devuelve verdadero si y solo si dos objetos se refieren al mismo objeto, es decir, x == y es verdadero.
Si cambiamos la clase Dog a la siguiente, ¿funcionará?
class Dog{ String color; public Dog(String s){ color = s; } //overridden method, has to be exactly the same like the following public boolean equals(Object obj) { if (!(obj instanceof Dog)) return false; if (obj == this) return true; return this.color.equals(((Dog) obj).color); } } |
La respuesta es no.
Ahora el problema es causado por el hashCode y es igual al contrato en Java. El método hashCode () es otro método en la clase Object.
El contrato es que si dos objetos son iguales (usando el método equals ()), deben tener el mismo hashCode (). Si dos objetos tienen el mismo código hash, es posible que no sean iguales.
La implementación predeterminada de public int hashCode () devuelve enteros distintos para objetos distintos. En este ejemplo en particular, debido a que no hemos definido nuestro propio método hashCode (), la implementación predeterminada devolverá dos enteros diferentes para dos perros blancos. Esto rompe el contrato.
Solución para el método contains () en Set
class Dog{ String color; public Dog(String s){ color = s; } //overridden method, has to be exactly the same like the following public boolean equals(Object obj) { if (!(obj instanceof Dog)) return false; if (obj == this) return true; return this.color.equals(((Dog) obj).color); } public int hashCode(){ return color.length();//for simplicity reason } } |
Referencias:
http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html