L'hash stesso viene calcolato dal metodo hashCode()
dell'oggetto che si sta tentando di memorizzare.
Quello che vedete qui è il calcolo del "bucket" per memorizzare l'oggetto in base all'hash h
. Idealmente, per evitare le collisioni, si otterrebbe lo stesso numero di serbatoi pari al massimo valore ottenibile di h
, ma potrebbe anche richiedere troppo memoria. Di conseguenza, di solito hai un numero inferiore di secchi con il rischio di collisioni.
Se h
è, ad esempio, 1000, ma si dispone solo di 512 bucket nell'array sottostante, è necessario sapere dove posizionare l'oggetto. Di solito, un'operazione mod
su h
sarebbe sufficiente, ma è troppo lenta. Data la struttura interna del HashMap
che la matrice sottostante sempre ha numero di contenitori pari a 2^n
, gli ingegneri della Sun potrebbero usare l'idea di h & (length-1)
, si fa un bitwise AND con un numero consistente di tutti 1
's, praticamente leggere solo il n
i bit più bassi dell'hash (che equivale a fare h mod 2^n
, solo molto più veloce).
Esempio:
hash h: 11 1110 1000 -- (1000 in decimal)
length l: 10 0000 0000 -- (512 in decimal)
(l-1): 01 1111 1111 -- (511 in decimal - it will always be all ONEs)
h AND (l-1): 01 1110 1000 -- (488 in decimal which is a result of 1000 mod 512)
fonte
2012-06-04 09:58:52
si può spiegare questo calcolo qui? – gnreddy
Suppone che 'length' sia un potere di 2? – LarsH
@LarsH Beh, sarebbe molto meglio se fosse una potenza di 2, quindi si otterrebbe un taglio pulito dei bit di ordine superiore. Come succede, l'implementazione di HashMap inizia con la dimensione 16 e infatti si moltiplica per due durante il ridimensionamento.Funzionerebbe ancora se non fosse una potenza di due, ma vorrai quanti più "on" bit possibile per 'length -1' per bilanciare lo spread tra i bucket – Bohemian