Repaso
English
Java CoreAvanzadoJV-34

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

  1. Siempre 1, porque los objetos iguales siempre comparten posición
  2. Probablemente 2: los hashCode por defecto difieren, así que van a buckets distintos (Opción correcta)
  3. Siempre 0, porque el set rechaza objetos sin hashCode
  4. Un error de compilación, porque hashCode es 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.

Términos clave

Practica esta pregunta en Repaso