【发布时间】:2013-09-10 00:11:05
【问题描述】:
即使 hashset 未排序,以下代码也会生成输出 [1,2]。
Set set = new HashSet();
set.add(new Integer(2));
set.add(new Integer(1));
System.out.println(set);
这是为什么呢?
【问题讨论】:
-
使用多个测试用例。包括20个数字,看看结果是否相同。
即使 hashset 未排序,以下代码也会生成输出 [1,2]。
Set set = new HashSet();
set.add(new Integer(2));
set.add(new Integer(1));
System.out.println(set);
这是为什么呢?
【问题讨论】:
编辑:从 Java 8 及更高版本开始,以下内容不再适用。这证明您不应该依赖未记录的 Java 行为。
这种行为是由几个不同的原因引起的:
HashMaps 和 HashSets 由数组备份因此,如果您将几个小 (
i 具有哈希码i
i
i
请注意,如果桶的初始数量太小,整数可能会落在没有编号的桶中:
HashSet<Integer> set = new HashSet<>(4);
set.add(5); set.add(3); set.add(1);
for(int i : set) {
System.out.print(i);
}
打印153。
【讨论】:
513。
根据文档,HashSet 不保证任何顺序概念,因此您所看到的很可能在 Java 的未来更新中发生变化。
但是,如果您想知道为什么 Java(截至目前)特定的 HashSet 实现会产生您所看到的结果:这是因为值 1 的 Integer 散列到内部条目中的某个位置HashMap 的表 在2 散列到的位置之前(请注意,HashSet 实际上由具有任意值的 HashMap 支持)。这是有道理的,因为Integer 对象的哈希码就是它的值。
事实上,即使你添加更多的数字也可以看到这一点(在一定范围内:入口表的大小,默认为16):
Set<Integer> set = new HashSet<>();
set.add(2);
set.add(1);
set.add(4);
set.add(3);
set.add(0);
System.out.println(set);
[0, 1, 2, 3, 4]
HashSet 的迭代是通过对内部条目表的迭代来实现的,这意味着表中较早的项目排在第一位。
【讨论】:
HashSet 是一个无序的集合。它没有保证,也没有“排序”的概念。有关详细信息,请参阅此答案:What is the difference between Set and List?
如果您需要有序、有序的集合,可以考虑使用TreeSet。
还有一个LinkedHashSet 表示未排序的有序集合。
【讨论】:
java 中的set 不应该是有序列表。请改用ArrayList。另请查看 Java Collection API 以获取更多参考。
【讨论】:
LinkedHashSet 通常是更好的选择。如果您想节省空间,并且可以容忍慢速(线性时间)查找,请仅使用 ArrayList。
Collections.binarySearch() 方法获得排序列表的对数时间 O(log n) 查找时间。
经过多次尝试和错误得出结论。这纯粹基于散列顺序。这就是我们称之为 HASH 集的原因。散列基于输入的长度。尝试 4 个单数和 4 个双数。你会得到结果。
【讨论】: