It's just a very beautiful edge case. The Hashcode Character is the value directly wrapped in it :
public int hashCode() { return Character.hashCode(value); } public static int hashCode(char value) { return (int)value; }
Thus, hashCode (a) = 97 or 0x61, b -> 0x62, c -> 0x63. HashMap also chooses buckets as follows:
public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/HashMap.java#610
The XOR is needed so that the upper bits also participate in the choice of the bake, because otherwise they are ignored (n is the number of buckets):
tab[i = (n - 1) & hash]
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/HashMap.java#629
Since we have a hash in this example is 0x61..0x63, all high bits are zero and play no role when hashing is mixed. The very operation of selecting a bake consists of simply discarding the higher bits of the obtained value. Thus, with any number of buckets> 2, these hashcodes guarantee getting into three consecutive bakes, because if we look at the last four bits of these hashcodes, we will see the following picture:
a 0001 b 0010 c 0011
if n> = 100 (four buckets or more), then these bits, which are responsible for the distribution, will always be preserved. The number of buckets by default is 16, which leads to the picture described.
I repeat that this is an edge case, and one cannot expect such behavior in general
probability2andprobabilityare confused by default locale