它不保证集合的迭代顺序;在 特别是,它不保证订单将保持不变 随着时间的推移
代码: -
Set<String> set = new HashSet<String>();
set.add("This is Tiger");
set.add("This is Cat");
set.add("This is Dog");
set.add("This is Elephant");
set.add("This is Parrot");
for(int i=0;i<100;i++){
for(String str:set){
System.out.println(str);
}
}
当我多次执行上面的代码时,我看到下面的输出
This is Elephant
This is Parrot
This is Cat
This is Dog
This is Tiger
我的问题是,当java文档说HashSet不能保证订单会随着时间的推移保持不变那么为什么我在执行程序的任何时候都看到上面的顺序相同。
是否根据字符串的哈希码进行内部排序?
更新: - 根据答案,当设置为静态时,看起来顺序是可预测的。 当我说可预测时,它并不意味着检索顺序与插入顺序相同,但无论第一次返回的顺序如何,它都会随着时间的推移而相同。
推理: - 我说如果添加5个静态条目,它将根据哈希码适合桶下的条目(列表/数组中没有任何位置)。让大象在第3斗,鹦鹉 - 5斗,猫 - 第6斗,狗 - 第9斗,虎 - 第10斗
现在,如果我添加长颈鹿,它将适合基于哈希码&gt;的第8个桶。现在,如果我迭代它将迭代从开始桶的条目。这将随着时间的推移而不变。因此,如果set是静态的,则可以预测。
我不会使用Hashset进行排序,但我有第三方代码将静态条目放在HashSet下,我无法更改。我需要出于某种原因预测这些条目中的顺序
答案 0 :(得分:0)
它不保证集合的迭代顺序;特别是,它不保证订单会随着时间的推移保持不变
你有一个静态的Set
。
当您使用新增内容修改现有Set
时,保证就会到位:
你是对的。您的程序将按预期返回。
Set<String> set = new HashSet<String>();
set.add("This is Tiger");
set.add("This is Cat");
set.add("This is Dog");
set.add("This is Elephant");
set.add("This is Parrot");
/*
This is Elephant
This is Parrot
This is Cat
This is Dog
This is Tiger
*/
for (String str : set) {
System.out.println(str);
}
现在让我们添加一个新条目,就像Set
中的长颈鹿一样。
Set<String> set2 = new HashSet<String>();
set.add("This is Tiger");
set.add("This is Cat");
set.add("This is Dog");
set.add("This is Elephant");
set.add("This is Parrot");
set.add("This is Giraffe");
/*
This is Elephant
This is Parrot
This is Cat
This is Giraffe
This is Dog
This is Tiger
*/
for (String str : set) {
System.out.println(str);
}
元素的顺序发生了变化。
要记住的是,您不应该依赖集合的迭代顺序,因为插入顺序是不可预测的,与可预测的插入顺序相反,如{{1} }
答案 1 :(得分:0)
除了对评论和其他答案中提到的保证的理解之外,还有一个HashMap
(HashSet
)的内置功能,根据该功能影响值的顺序差不多:
实施说明。
此映射通常用作分箱(分区)哈希表,但是 当垃圾箱变得太大时,它们会变成垃圾箱 TreeNodes,每个结构与中的结构类似 java.util.TreeMap中。大多数方法都尝试使用普通箱,但是 适用时中继到TreeNode方法(只需检查 节点的实例)。可以遍历TreeNodes的bin 像其他人一样使用,但另外支持更快的查找 人口过剩时。但是,由于绝大多数的垃圾箱 正常使用不会人满,检查是否存在 在表格方法的过程中,树箱可能会被延迟。
这实际上意味着在一位中的特定数量的值之后,HashMap
将桶从链表重构到树映射重组。这会影响迭代中值的顺序。