Per motivi di praticità, hashCode() restituisce un int firmato. 2 32 valori possibili. Uno potrebbe banalmente essere un long invece di un int e mi farebbe cambiare leggermente il resto di questa risposta.
L'essenza di tutto questo è il principio del pigeonhole . Se hai m elementi e provi a metterli in n box e m > n , allora avrai due elementi che vanno nella stessa casella.
Osserviamo hashCode per Long - che può avere 2 64 valori. Dal 2 64 > 2 32 avrai due valori con lo stesso valore.
public int hashCode() {
return (int)(value ^ (value >>> 32));
}
Quindi, lascia scrivere un codice rapido.
System.out.println(Long.valueOf(0).hashCode());
System.out.println(Long.valueOf(-1).hashCode());
System.out.println(Long.valueOf(0).equals(Long.valueOf(-1)));
System.out.println(Long.valueOf(0).hashCode() == Long.valueOf(-1).hashCode());
Stampa:
0
0
false
true
E ce l'abbiamo. Due numeri Uno di questi è 0 e l'altro è -1 che ha lo stesso codice hash, ma non lo stesso numero.
Il valore esadecimale di -1 è 0xffffffffffffffff che quando fai un 0xffffffff ^ 0xffffffff ottieni 0
Ma aspetta! Cosa succede se abbiamo usato long per l'hashCode invece!
Come ho detto, è solo un problema leggermente diverso. Dovrei iniziare a scavare in un'altra classe che ha la possibilità di avere più valori di hashCode, come BigInteger o Stringa o Inet6Address (2 128 valori possibili ). Tutto ciò che fa è rendere il calcolo dell'hashCode un po 'più difficile da fare proprio qui (quelli sono più lunghi di una linea con operazioni a due bit). Non cambia il fatto che hashCode, essendo un valore di dimensione fissa, è soggetto al principio del pigeonhole.