49 - Java Hashing (Método HashCode )
49 - Java Hashing (Método HashCode )
Java Hashing
Todos los objetos en Java tiene dos mtodos muy importantes: el
mtodo hashCode () y el mtodo equals (). Estos mtodos estn
diseados para ser sobrescritos de acuerdo a su contrato
general.
El contrato de un HashCode
El contrato del mtodo hashCode () dice:
"Si dos objetos son iguales usando equals (), entonces la invocacin
a hashCode () de ambos objetos debe retornar el mismo valor"
Entonces, la pregunta que surge es: es necesario que siempre se cumpla esa
oracin?
Considerar una clase que tiene una implementacin correcta del mtodo
equals(), qu pasara si no se obedece el contrato anterior?
Para responder a esa pregunta, se deben considerar dos situaciones:
Objetos que son iguales, pero retornan diferentes hashCode
Objetos que no son iguales, pero retornan el mismo hashCode
Conocimiento: HashCode
Prof. Viviana Alvarez Tom
Conocimiento: HashCode
Prof. Viviana Alvarez Tom
Conocimiento: HashCode
Prof. Viviana Alvarez Tom
Conocimiento: HashCode
Prof. Viviana Alvarez Tom
2.Para cada campo significativo f en el objeto (es decir, cada campo que se tiene
en cuenta al ejecutar un equals()), hacer lo siguiente:
Si
el
campo
es
un
double,
calcular
long
l = Double.doubleToLongBits(f); c = (int) (l ^ (l >>> 32));
Si el campo es
c = f.hashCode()
una
referencia
un
objeto,
calcular
3.Retornar result
Conocimiento: HashCode
Prof. Viviana Alvarez Tom
Como vemos elegimos la constante 37. La idea es elegir un nmero que sea un nmero
primo. Podemos elegir cualquier nmero primo. Al usar un nmero primo los objetos se
distribuirn mejor en los lotes. Pueden aprender ms sobre este algoritmo y la
distribucin que genera buscando en Internet.
Conocimiento: HashCode
Prof. Viviana Alvarez Tom
Apache HashCodeBuilder
Como estamos aprendiendo, no es siempre fcil retornar un buen valor de hashCode.
Por suerte existen clases que nos pueden ayudar.
El paquete org.apache.commons.lang.builder de Jakarta-Commons contiene la clase
HashCodeBuilder que est diseada para ayudarnos a implementar el mtodo
hashCode(). Muchos desarrolladores luchan por escribir sus hashCode cuando existe
esta clase que nos simplifica el proceso.
As es como quedara la clase de prueba anterior usando la clase HashCodeBuilder:
Noten que los dos nmeros del constructor del HashCodeBuilder son dos nmeros
impares distintos a cero - estos nmeros ayuda a evitar la colisin de valores de
hashCode en otros objetos.
Si se necesita, se puede invocar al hashCode() de la superclase usando
appendSuper(int).
Conocimiento: HashCode
Prof. Viviana Alvarez Tom
Conocimiento: HashCode
Prof. Viviana Alvarez Tom
}
public int getEdad() {
return edad;
}
public void setEdad(int edad) {
this.edad = edad;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Empleado) {
Empleado emp = (Empleado)obj;
return (emp.nombre.equals(nombre) && emp.edad == edad);
}
return false;
}
@Override
public int hashCode() {
return nombre.length() + edad;
}
public static void main(String[] args) {
Empleado e = new Empleado("muhammad", 24);
Map map = new HashMap();
map.put(e, "Muhammad Ali Khojaye");
// encuentra el resultado
System.out.println(map.get(e));
Conocimiento: HashCode
Prof. Viviana Alvarez Tom
e.nombre = "abid";
// el map devolver null porque no lo encuentra
System.out.println(map.get(e));
// otra vez devolver null
System.out.println(map.get(new Empleado("muhammad", 24)));
}
}