我写了以下代码,
public int longestConsecutive(int[] nums) {
Set<Integer> num_set = new HashSet<Integer>();
for (int num : nums) {
num_set.add(num);
System.out.println("num_set: " + num_set.toString());
}
然后我有测试用例,
int[] nums = {100, 4, 200, 1, 3, 2};
然后在最后一行输出中,控制台显示
num_set: [1, 2, 3, 100, 4, 200]
我想知道为什么添加操作后更改了先前的顺序。
答案 0 :(得分:7)
统计HashSet文档
对于集合的迭代顺序,它否保证;特别是,它不能保证订单会在一段时间内保持不变。
如果要使用保持自然顺序的Set
,请改用SortedSet。
一个Set,进一步提供其元素的总体排序。元素使用其自然顺序或通过通常在排序集创建时提供的Comparator进行排序。
编辑:
Set
确实没有说任何有关其元素顺序的信息。例如,如果两个Set包含相同的元素并且具有相同的大小,则两个Set相等。 Set
的迭代顺序取决于实现方式,并且在版本之间可能会有所不同,因此您不应对此做任何假设。它可能取决于#hashCode
的值,但也可能取决于插入顺序或将来的其他操作。但是,我们不在乎,因为如果您这样做,则应该改用List
或SortedSet
。
答案 1 :(得分:1)
格兰斯已经回答了您的问题。我仍然想添加一些内容:Java库中有接口,可为开发人员提供合同,并保证可以以哪种方式使用它们。
就像您的问题一样,基本界面Set
不包含重复元素的集合。
您的implementor
HashSet(已经明确说明了不能保证订购的事实),在这种情况下,您应该不要与订单有关的承诺。
对于集合的迭代 order ,它没有没有保证;特别是,它不能保证顺序会随着时间的推移保持恒定。
具体地说,Java提供了另一个接口SortedSet来确保您要订购:
一个Set,进一步提供其元素的总体排序。元素使用其自然顺序或通过通常在排序集创建时提供的Comparator进行排序。
因此,在您的情况下,您应该找到一个实现接口 implementor
的{{1}},例如TreeSet。
通常我们不太关心实现细节,因为可以在不知情的情况下对其进行调整/更改,而另一方面,承诺是库开发人员在官方文档将始终保留。
答案 2 :(得分:0)
您似乎想保留插入顺序。为此有一个名为LinkedHashSet
的类。这是为您提供的一些示例代码:
int[] nums = {100, 4, 200, 1, 3, 2};
Set<Integer> ints = new LinkedHashSet<>();
for(int i : nums) {
ints.add(i);
}
System.out.println(ints);
上面的代码显示:[100, 4, 200, 1, 3, 2]
正如documentation所说:
Set接口的哈希表和链表实现,具有可预测的迭代顺序。此实现与HashSet的不同之处在于,它维护贯穿其所有条目的双向链接列表。此链接列表定义了迭代顺序,即将元素插入集合(插入顺序)的顺序。请注意,如果将元素重新插入到集合中,则插入顺序不会受到影响。 (如果在调用s.contains(e)之前立即返回true的情况下调用s.add(e),则将元素e重新插入到set s中。)