>>>
is the logical right shift (no sign-extension) (JLS 15.19 Shift Operators), and ^
is the bitwise exclusive-or (JLS 15.22.1 Integer Bitwise Operators).
As to why this is done, the documentation offers a hint: HashMap
uses power-of-two length tables, and hashes keys by masking away the higher bits and taking only the lower bits of their hash code.
// HashMap.java -- edited for conciseness
static int indexFor(int h, int length) {
return h & (length-1);
}
public V put(K key, V value) {
int hash = hash(key.hashCode());
int index = indexFor(hash, table.length);
// ...
}
So hash()
attempts to bring relevancy to the higher bits, which otherwise would get masked away (indexFor
basically discards the higher bits of h
and takes only the lower k
bits where length == (1 << k)
).
Contrast this with the way Hashtable
(which should have NOT a power-of-two length table) uses a key's hash code.
// Hashtable.java -- edited for conciseness
public synchronized V get(Object key) {
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % table.length;
// ...
}
By doing the more expensive %
operation (instead of simple bit masking), the performance of Hashtable
is less sensitive to hash codes with poor distribution in the lower bits (especially if table.length
is a prime number).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…