Una clase sobrescribe equals pero NO hashCode. ¿Cuál es el resultado probable?
class P {
String n;
P(String n) { this.n = n; }
@Override public boolean equals(Object o) {
return o instanceof P p && p.n.equals(n);
}
}
Set<P> s = new HashSet<>();
s.add(new P("a"));
s.add(new P("a"));
System.out.println(s.size());Opciones
- Siempre 1, porque los objetos iguales siempre comparten posición
- Probablemente 2: los hashCode por defecto difieren, así que van a buckets distintos (Opción correcta)
- Siempre 0, porque el set rechaza objetos sin hashCode
- Un error de compilación, porque
hashCodees obligatorio en Java
Respuesta
Lo más probable es 2: el hashCode por defecto difiere por objeto, así que caen en buckets distintos y equals ni siquiera se llama
Por qué
Sin override, hashCode() viene de Object y se basa en la identidad del objeto, así que dos objetos P distintos casi siempre obtienen hash codes diferentes.
HashSet usa el hash para elegir un bucket. Los dos objetos van a buckets distintos, así que equals nunca se compara y ambos se guardan: tamaño 2, aunque equals diga que son iguales.
Esto rompe el contrato. Solución: sobrescribe también hashCode con Objects.hash(n).
Recuerda
Contrato equals/hashCode roto = duplicados en colecciones hash.