Boolean.hashCode ()


122

Il hashCode()metodo della classe Boolean è implementato in questo modo:

public int hashCode() {
    return value ? 1231 : 1237;
}

Perché usa 1231 e 1237? Perché non qualcos'altro?


1
Questi due numeri sono numeri primi sufficientemente grandi. Si prega di leggere l' articolo su Hash Table su Wikipedia per ulteriori informazioni.
Boris Pavlović

Risposte:


140

1231 e 1237 sono solo due numeri primi arbitrari (sufficientemente grandi) . Altri due numeri primi grandi andrebbero bene.

Perché i numeri primi?
Supponiamo per un secondo di aver scelto numeri composti (non primi), diciamo 1000 e 2000. Quando si inseriscono valori booleani in una tabella hash, true e false andrebbero nel bucket 1000 % Nresp 2000 % N(dove Nè il numero di bucket).

Ora notalo

  • 1000 % 8 stesso secchio di 2000 % 8
  • 1000 % 10 stesso secchio di 2000 % 10
  • 1000 % 20 stesso secchio di 2000 % 20
  • ....

in altre parole, porterebbe a molte collisioni .

Questo perché la fattorizzazione di 1000 (2 3 , 5 3 ) e la fattorizzazione di 2000 (2 4 , 5 3 ) hanno tanti fattori comuni. Pertanto vengono scelti i numeri primi, poiché è improbabile che abbiano fattori comuni con la dimensione del secchio.

Perché numeri primi grandi . 2 e 3 non andrebbero bene?
Quando si calcolano i codici hash per oggetti compositi, è comune aggiungere i codici hash per i componenti. Se vengono utilizzati valori troppo piccoli in un set di hash con un numero elevato di bucket, c'è il rischio di finire con una distribuzione non uniforme degli oggetti.

Le collisioni sono importanti? I booleani hanno comunque due valori diversi?
Le mappe possono contenere valori booleani insieme ad altri oggetti. Inoltre, come sottolineato da Drunix, un modo comune per creare funzioni hash di oggetti compositi è riutilizzare le implementazioni del codice hash dei sottocomponenti, nel qual caso è bene restituire numeri primi grandi.

Domande correlate:


1
Suppongo che siano sufficientemente grandi. Per ottenere un mcd maggiore di 1, avrai bisogno di almeno 2*1231 = 2462bucket. Le collisioni sono un problema in una situazione del genere?
aioobe

2
È interessante però che non siano realmente "abbastanza grandi" considerando ciò che può stare in un int. Suppongo che siano abbastanza grandi da funzionare bene con JDK Hashtable, ma comunque abbastanza piccoli da ridurre al minimo i costi di calcolo.
Thilo

2
Sì, mi ha colpito anche il fatto che non siano così grandi. Ma credi che ci sia un costo maggiore con numeri primi più grandi?
aioobe

3
@Thilo avresti bisogno di un multiplo di 1231 * 1237 = 1.522.747 secchi prima che si scontrassero, che è abbastanza grande abbastanza
ratchet freak

2
Direi che portare a collisioni con il conteggio dei bucket non è davvero un problema con boolean, ma più la costruzione comune su come ottenere l'hashcode di un oggetto composto, vale a dire moltiplicando gli hashcode dei componenti con alcune costanti e sommandoli.
Drunix

2

Oltre a tutto ciò che è stato detto sopra, può anche essere un piccolo easter egg degli sviluppatori:

vero: 1231 => 1 + 2 + 3 + 1 = 7

7 - è un numero fortunato nelle tradizioni europee;

falso: 1237 => 1 + 2 + 3 + 7 = 13

13 (aka Devil's dozen) - numero sfortunato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.