Dlaczego HashSet zezwala na równe elementy, jeśli kody skrótu są różne?

TheHashSet klasa madodaj (Obiekt o) metoda, która nie jest dziedziczona z innej klasy. Javadoc dla tej metody mówi:

Dodaje określony element do tego zestawu, jeśli nie jest jeszcze obecny. Bardziej formalnie dodaje określony elemente do tego zestawu, jeśli ten zestaw nie zawiera żadnego elementue2 takie(e==null ? e2==null : e.equals(e2)). Jeśli ten zestaw już zawiera element, wywołanie pozostawia zestaw bez zmian i zwracafalse.

Innymi słowy, jeśli dwa obiekty są równe, drugi obiekt nie zostanie dodany, a zestaw HashSet pozostanie taki sam. Odkryłem jednak, że nie jest to prawdą, jeśli obiektye ie2 mają różne hashcodes, mimo żee.equals(e2). Oto prosty przykład:

import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;

public class BadHashCodeClass {

    /**
     * A hashcode that will randomly return an integer, so it is unlikely to be the same
     */
    @Override
    public int hashCode(){
        return new Random().nextInt();
    }

    /**
     * An equal method that will always return true
     */
    @Override
    public boolean equals(Object o){
        return true;
    }

    public static void main(String... args){
        HashSet<BadHashCodeClass> hashSet = new HashSet<>();
        BadHashCodeClass instance = new BadHashCodeClass();
        System.out.println("Instance was added: " + hashSet.add(instance));
        System.out.println("Instance was added: " + hashSet.add(instance));
        System.out.println("Elements in hashSet: " + hashSet.size());

        Iterator<BadHashCodeClass> iterator = hashSet.iterator();
        BadHashCodeClass e = iterator.next();
        BadHashCodeClass e2 = iterator.next();
        System.out.println("Element contains e and e2 such that (e==null ? e2==null : e.equals(e2)): " + (e==null ? e2==null : e.equals(e2)));
    }

Wyniki głównej metody to:

Instance was added: true
Instance was added: true
Elements in hashSet: 2
Element contains e and e2 such that (e==null ? e2==null : e.equals(e2)): true

Jak wyraźnie widać na powyższym przykładzie, HashSet był w stanie dodać dwa elementye.equals(e2).

Zakładam, że tak jestnie błąd w Javie i że w rzeczywistości istnieje jakieś doskonale racjonalne wyjaśnienie, dlaczego tak jest. Ale nie wiem, co dokładnie. czego mi brakuje?

questionAnswers(5)

yourAnswerToTheQuestion