Categorías
Basics Common Methods

Java hashCode () y equals () Contrato para el método de conjunto contiene (Objeto o)

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");
}
  ¿Otro "Java pasa por referencia o por valor"?

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.

  diagrama de jerarquía de clases java io

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

Por Programación.Click

Más de 20 años programando en diferentes lenguajes de programación. Apasionado del code clean y el terminar lo que se empieza. ¿Programamos de verdad?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *