Pregunta de entrevista técnica #1 ¿En java para qué sirven los métodos equals() y hashCode() en un objeto?

Aquí comienzo una serie de pequeños artículos para aprender a responder a preguntas típicas de una entrevista técnica, por un lado aprenderás a desenvolverte mejor y a la vez obtendrás conceptos interesantes que te pueden ser útiles en tu día a día, empezamos por un clásico de los clásicos, los dos métodos que puedes encontrar por defecto en toda clase que extienda de Object en Java, o sea, todas.

equals()

El método equals() de la clase Object se utiliza para comprobar si el objeto actual es igual o no al objeto que se pasa. Por defecto, comprueba la dirección de memoria del objeto de las instancias. Si ambos objetos tienen la misma dirección de memoria, entonces son iguales.

hashCode()

El hashCode(), de la clase Object, se utiliza para identificar un objeto de forma única. De forma predeterminada, devuelve la dirección de memoria del objeto en un formato de número entero.

La ventaja de utilizar juntos equals() y hashCode()

Para las clases IntegerFloatString, etc, no tienes que preocuparte por ellas. Pero para tus propias clases, es posible que desee sobrescribir estos métodos, siempre para casos especiales y no todo siempre. 

Por ejemplo, si deseas usarlo como una clave en un Map o si no quieres tener objetos duplicados y esa duplicación está basada en algunos campos de identificación de la clase.

Al sobrescribirlo, nos aseguramos que equals() se base en hashCode() y hashCode() se base en un valor único. Entonces, si obj1.equals(obj2) es true, entonces obj1.hashCode() == obj2.hashCode() deberá ser true. Si no, pueden comportarse de formas muy extrañas.

Ejemplo:

Supongamos que tengo una identificación int (int id) en mi clase que debe ser única para cada objeto y no me importa si hay otros campos duplicados excepto este. Y quiero hacer de este objeto una clave para un Map. Entonces sobrescribimos los métodos hashCode() y equals() de esta manera:

private int id;
@Override
public int hashCode(){
    return this.id;
}
@Override
public int equals(Object obj){
    if(obj == null) 
    	return false;
    if(! obj instanceOf ThisClassName) 
    	return false;
    return this.id == obj.id;
}