I'm not sure calling it a coincidence is the right answer. There is no chance involved. It results of the hash functions being used, the small values you put in the HashSet and the small amount of elements you put in the Set.
For Integer, hashCode()
is the int value of the Integer.
HashMap (and HashSet) do an additional hashing on the value returned by hashCode
, but this additional hashing doesn't change the value for such small numbers as you added to the HashSet.
Finally, the bucket that each integer is put into is the modified hash code modulu the capacity of the HashSet. The initial capacity of a HashSet/HashMap is 16.
Therefore 2 is added to bucket 2, 7 is added to bucket 7, etc...
When you iterate over the elements of the HashSet, the buckets are visited in order, and since each bucket has at most a single element, you get the numbers sorted.
Here is how the bucket is computed :
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
static int hash(int h) { // for the small integers you put in the set, all the values being
// xored with h are 0, so hash(h) returns h
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
static int indexFor(int h, int length) {
return h & (length-1); // table.length is the initial capacity - 16,
// so for h <= 15, indexFor(h,table.length)=h
}
Therefore, the buckets of 2,7,3,9,6 are 2,7,3,9,6 respectively.
The enhanced for loop you use to iterate over the HashSet visits the buckets in order, and for each bucket iterates over its entries (which are stored in a linked list). Therefore, for your input, 2 is visited first, followed by 3, 6, 7 and 9.
If you add numbers higher than 15, both the hash
method and the indexFor
method (assuming you didn't change the default capacity of the HashSet) would prevent the numbers from being sorted when iterated by the HashSet iterator.