Here is a good explanation of how HashMap works in Java 8. The following is a snippet from the same blog.
To understand this in the first place, we need to understand how the index is calculated:
Match the hash code with the index in the array. The easiest way to do this is to perform a modulo operation on the hash code and the length of the array, for example, the hash (key)% n. Using modulo ensures that the index i is always between 0 and n.
i = hash% n;
For a HashMap in Java, the index is calculated by the following expression:
i = (n - 1) & hash;
In this expression, the variable n refers to the length of the table, and hash refers to the key hash.
Since we compute the module by the bitmask ((n - 1) and hash), any bit above the high bit n - 1 will not be used by the module. For example, given n = 32 and 4 hash codes for the calculation. When executed modulo directly without hash code conversion, all indexes will be 1. Collision is 100%. This is due to the fact that mask 31 (n - 1), 0000 0000 0000 0000 0000 0000 0001 1111, makes any bit above position 5 unused in the number h. To use these high-order bits, the HashMap shifts them 16 positions to the left h >>> 16 and expands with the low-order bits (h ^ (h >>> 16)). As a result, the resulting module has less collision.
source share