Personalizar los métodos equals() y hashCode() son parte del día a día en Java, sobretodo si trabajamos con colecciones, las colecciones juegan un papel crucial en la gestión y organización de datos. Los Set y List son de las más utilizadas. Sin embargo, para optimizar su rendimiento y evitar problemas como la duplicidad de objetos, es fundamental personalizar los métodos equals() y hashCode().
¿Qué son los métodos equals() y hashCode()?
Estos dos métodos originalmente son definidos en la clase Object y como sabrás en Java todos las clases u objetos son hijos de forma directa o indirecta de la clase Object.
equals() se utiliza para comparar dos objetos para igualdad lógica, mientras que hashCode() devuelve un valor entero que representa el objeto. Juntos, estos métodos aseguran que las colecciones como Set y Map funcionen correctamente.
java.util.Set y los métodos equals() y hashCode()
Un Set en Java no permite elementos duplicados. Para determinar si dos objetos son iguales, el Set utiliza los métodos equals() y hashCode(). Si estos métodos no están correctamente implementados, es posible que se permitan duplicados, esto es algo muy común cuando creamos nuestras propias clases y crear clases propias es algo que sucede en cualquier sistema.
java.util.List y los métodos equals() y hashCode()
En un List, aunque se permiten elementos duplicados, los métodos equals() y hashCode() son útiles para operaciones como contains() e indexOf(). Estos métodos dependen de equals() para verificar si un objeto existe en la lista, esto también aplica para cualquier otro tipo de colección que implemente métodos para validar la existencia previa de un item.
Caso de uso
Es muy común que los nuevos desarrolladores o devs que vienen de otros lenguajes tengan ciertas dificultades en implementar la duplicidad en colecciones o la validación de exista de elementos dentro de una colección, así que planteemos un caso de uso real.
Tenemos un servicio o una clase de lógica que tiene una lista de personas, en esa lista de persona no se permiten duplicados, y tenemos un campo que nos ayuda a determinar cuando un item es único, el campo es el número de identificación, eso quiere decir que un número de identificación solo puede existir una sola vez dentro de la colección.

Vamos a implementarlo de dos formas, la primera es con List y la segunda con Set, es posible implementarlo con otras colecciones pero yo cubriré estas dos, aunque seguramente los cambios para adaptarlo a otras colecciones son mínimos.
Primero definimos la clase Persona
import java.util.Objects; public class Persona { private String nombre; private int edad; private String numeroIdentificacion; public Persona(String nombre, int edad, String numeroIdentificacion) { this.nombre = nombre; this.edad = edad; this.numeroIdentificacion = numeroIdentificacion; } // Getter and Setter @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Persona persona = (Persona) o; return Objects.equals(numeroIdentificacion, persona.numeroIdentificacion); } @Override public int hashCode() { return Objects.hash(numeroIdentificacion); } }
En este código ya hemos sobrescrito los métodos equals y hashCode, la mayoría de IDEs nos permiten sobrescribir a través de algún atajo del teclado, sin embargo es importante que lo entendamos.
Método equals()
Este método compara dos objetos Persona. Primero, verifica si los objetos son iguales por referencia. Luego, verifica si el objeto pasado es null o si son de diferentes clases. Finalmente, compara el atributo numeroIdentificacion.
Método hashCode()
Este método genera un código hash utilizando el atributo numeroIdentificacion. Es crucial que equals() y hashCode() estén alineados, es decir, dos objetos iguales deben tener el mismo código hash.
Ahora veamos la implementación con Set.
import java.util.HashSet; import java.util.Set; public class Main { public static void main(String[] args) { Set<Persona> personas = new HashSet<>(); personas.add(new Persona("Juan", 30, "12345")); personas.add(new Persona("Ana", 25, "12345")); System.out.println("Tamaño del Set: " + personas.size()); // Debe imprimir 1 } }
Gracias a la correcta implementación de equals() y hashCode(), el Set reconoce que los dos objetos Persona tienen el mismo numeroIdentificacion y no permite duplicados, recordemos que en este ejemplo los objetos son iguales cuando tienen el mismo número de identificación, sin importar si los otros datos son diferentes entre sí.
Ahora veamos la implementación con List.
import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<Persona> personas = new ArrayList<>(); personas.add(new Persona("Ana", 25, "67890")); personas.add(new Persona("Carlos", 40, "12345")); System.out.println("¿Lista contiene a Ana con ID 67890?: " + personas.contains(new Persona("Ana", 25, "67890"))); // Debe imprimir true } }
La implementación de equals() permite que el método contains() de List funcione correctamente, identificando que el objeto Persona(“Ana”, 25, “67890”) ya existe en la lista.
Personalizar los métodos equals() y hashCode() es esencial para optimizar el rendimiento y la funcionalidad de las colecciones en Java. Asegura que los Set no contengan duplicados y permite operaciones precisas en List. Implementar estos métodos correctamente no solo mejora la eficiencia, sino que también previene errores y comportamientos inesperados en tus aplicaciones.
Y como dije antes esto es algo del día a día de cualquier dev, así que es conocimiento vital que necesitas entender y aprender a implementar.