A hash in the Java hash table
I’ve been digging the hash table source code.
And discover how hashing happens:
int index = (hash & 0x7FFFFFFF) % tab.length;
I don’t understand why bitwise AND is used here?
If we convert 0x7FFFFFFF to binary, we get =
111 1111 1111 1111 1111 1111 1111 1111 1111
As far as I know, if the first and second digits = 1, then bitwise AND will give 1
So if we get some object hash code, e.g. 2314539
convert it to binary and perform an & operation, we actually get the same number:
2314539 = 10 0011 0101 0001 0010 1011
10 0011 0101 0001 0010 1011
&
11 1111 1111 1111 1111 1111
=
10 0011 0101 0001 0010 1011
10 0011 0101 0001 0010 1011 = 2314539
As you can see, nothing has changed to this operation. So what’s the point here?
Solution
Let’s start with the meaning of remainder (%
) in Java. According to JLS 15.17.3
:
The remainder operation for operands that are integers after binary numeric promotion (§5.6.2) produces a result value such that
(a/b)*b+(a%b)
is equal toa
.It follows from this rule that the result of the remainder operation can be negative only if the dividend is negative, and can be positive only if the dividend is positive. Moreover, the magnitude of the result is always less than the magnitude of the divisor.
Suppose index is calculated as
index = hash % tab.length.
If so, a negative value of the hash
will result in a negative value of index
.
But we’re going to subscript tab
with index
, so it has to be between 0
and tab.length
Instead, the actual computation first maps the hash to a non-negative number by masking out the
sign bits. It then performs the remainder operation.
So what’s a point here?
- Your working example is for positive
hash
values.&
does have an impact on negativehash
values. - The key is to avoid negative
hash
values giving negativeindex
values, which will result inan ArrayIndexOutOfBoundsException
.