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?