我在main
方法上有以下代码,当我遍历Set
并打印值时,值已经排序。原因是什么?
Set<Integer> set = new HashSet<Integer>();
set.add(2);
set.add(7);
set.add(3);
set.add(9);
set.add(6);
for(int i : set) {
System.out.println(i);
}
输出:
2
3
6
7
9
答案 0 :(得分:4)
这只是巧合。 HashSet
不保留或保证任何订购。
它不保证集合的迭代顺序;在 特别是,它不保证订单将保持不变 随着时间的推移。
答案 1 :(得分:4)
我不确定这是巧合是正确的答案。没有机会参与其中。它是使用散列函数的结果,放在HashSet中的小值以及放入Set中的少量元素。
对于Integer,hashCode()
是整数的int值。
HashMap(和HashSet)对hashCode
返回的值执行额外的散列处理,但是这个额外的散列不会更改您添加到HashSet中的小数字的值。 / p>
最后,每个整数放入的存储桶是修改后的哈希码,模块化了HashSet的容量。 HashSet / HashMap的初始容量为16。
因此2添加到桶2,7添加到桶7等...
当您遍历HashSet的元素时,将按顺序访问存储桶,并且由于每个存储桶最多只有一个元素,因此您可以对数字进行排序。
以下是计算存储桶的方式:
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
}
因此,2,7,3,9,6的分别为2,7,3,9,6。
用于迭代HashSet的增强for循环按顺序访问存储桶,并且每个存储桶迭代其条目(存储在链表中)。因此,对于您的输入,首先访问2,然后访问3,6,7和9。
如果您添加的数字高于15,hash
方法和indexFor
方法(假设您没有更改HashSet的默认容量)将阻止数字排序当由HashSet迭代器迭代时。
答案 2 :(得分:2)
这只是一次意外。我试过了:
final Set<Integer> set = new HashSet<Integer>();
set.add(2);
set.add(17);
set.add(32);
set.add(92);
set.add(63);
我得到了17 32 2 92 63
。它不在排序顺序中,因为HashSet
不保留排序顺序或它们的添加顺序。