测试代码
@Test
public void test01(){
HashSet set = new HashSet();
for (int i = 0; i<=65536; i++) {
set.add(i);
}
System.out.println(set);
}
测试结果
原因
为什么正整数会有序输出?
我们知道整数等hash值等于本身
public static int hashCode(int value) {
return value;
}
HashSet会把添加元素等哈希值重新计算得到新Hash值
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
代码中h为元素的hash值,HashSet会将hash值在hashSet会把hash值无符号右移16位,再与hash值异或运算。 (h = key.hashCode()) ^ (h >>> 16)
因为>>>是无符号右移16位,因为2的16次方为65536,所以对于0<=hashcode<=65536的整数,右移16位都为0,0异或任何数都等于本身,所以右移后的值异或本身的hash值都为本身hash值。
然后HashSet根据新的hash值计算出元素在table表中的位置。
(p = tab[i = (n - 1) & hash])
(n - 1) & hash得到在元素table表中位置。
&按位与的运算规则是将两边的数转换为二进制位,然后运算最终值,运算规则即(两个为真才为真)1&1=1 , 1&0=0 , 0&1=0 , 0&0=0
n第一次扩容为16,所以n-1=15,转换为二进制为1111 ,与任何数字相与都为自己本身,在集合容量到达12时扩容两倍,n为32,
此时n-1=31,二级制为1 1111,由此可见只要按照二倍扩容,添加数字为整数为正数数,数字不是很大,那么在集合中的排序就是有序的,且按照整数大小顺序排列