Java HashSet 中元素的排序

发布于 2025-01-07 16:13:13 字数 477 浏览 0 评论 0原文

为什么第二组和第三组保持顺序:

Integer[] j = new Integer[]{3,4,5,6,7,8,9};
LinkedHashSet<Integer> i = new LinkedHashSet<Integer>();
Collections.addAll(i,j);
System.out.println(i); 

HashSet<Integer> hi = new HashSet<Integer>(i);
System.out.println(hi); 

LinkedHashSet<Integer> o = new LinkedHashSet<Integer>(hi);
System.out.println(o); 

这是我得到的输出:

3,4,5,6,7,8,9
3,4,5,6,7,8,9
3,4,5,6,7,8,9

Why do the second and third sets preserve order:

Integer[] j = new Integer[]{3,4,5,6,7,8,9};
LinkedHashSet<Integer> i = new LinkedHashSet<Integer>();
Collections.addAll(i,j);
System.out.println(i); 

HashSet<Integer> hi = new HashSet<Integer>(i);
System.out.println(hi); 

LinkedHashSet<Integer> o = new LinkedHashSet<Integer>(hi);
System.out.println(o); 

Here's the output I get:

3,4,5,6,7,8,9
3,4,5,6,7,8,9
3,4,5,6,7,8,9

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

千里故人稀 2025-01-14 16:13:13

第二个(仅使用HashSet)只是一个巧合。来自 JavaDocs

此类实现 Set 接口,由哈希表(实际上是 HashMap 实例)支持。它不保证集合的迭代顺序; 特别是,它不能保证顺序随着时间的推移保持不变。此类允许 null 元素。

第三个 (LinkedHashSet) 是 设计是这样的:

Set 接口的哈希表和链表实现,具有可预测的迭代顺序。此实现与 HashSet 的不同之处在于,它维护一个贯穿其所有条目的双向链表。该链表定义了迭代顺序,即元素插入集合的顺序(插入顺序)。请注意,如果将元素重新插入集合中,插入顺序不会受到影响。 (如果在调用之前 s.contains(e) 返回 true 时调用 s.add(e),则元素 e 会重新插入到集合 s 中。)

The second one (just using HashSet) is only a coincidence. From the JavaDocs:

This class implements the Set interface, backed by a hash table (actually a HashMap instance). It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time. This class permits the null element.

The third one (LinkedHashSet) is designed to be like that:

Hash table and linked list implementation of the Set interface, with predictable iteration order. This implementation differs from HashSet in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order). Note that insertion order is not affected if an element is re-inserted into the set. (An element e is reinserted into a set s if s.add(e) is invoked when s.contains(e) would return true immediately prior to the invocation.)

鲜血染红嫁衣 2025-01-14 16:13:13

@Behrang的答案很好,但更具体地说,HashSet似乎与LinkedHashSet顺序相同的唯一原因是integer.hashCode( ) 恰好是整数值本身,因此数字恰好在 HashSet 内部存储中按顺序排列。这是高度特定于实现的,正如@Behrang所说,这确实是一个巧合。

例如,如果您使用 new HashSet<>(4) 将存储桶的初始数量设置为 4(而不是 16),那么您可能会得到以下输出

HashSet<Integer> hi = new HashSet<Integer>(4);
...
[3, 4, 5, 6, 7, 8, 9]
[8, 9, 3, 4, 5, 6, 7]
[8, 9, 3, 4, 5, 6, 7]

: value >= 16,你可能会得到这样的结果:

Integer[] j = new Integer[] { 3, 4, 5, 6, 7, 8, 9, 16 };
...
[3, 4, 5, 6, 7, 8, 9, 16]
[16, 3, 4, 5, 6, 7, 8, 9]
[16, 3, 4, 5, 6, 7, 8, 9]

@Behrang's answer is good but to be more specific, the only reason why the HashSet seems to be in the same order as the LinkedHashSet is that integer.hashCode() happens to be the integer value itself so the numbers happen to be in order in the HashSet internal storage. This is highly implementation specific and as @Behrang says, really a coincidence.

For example, if you use new HashSet<>(4) which sets the initial number of buckets to be 4 (instead of 16) then you might have gotten the following output:

HashSet<Integer> hi = new HashSet<Integer>(4);
...
[3, 4, 5, 6, 7, 8, 9]
[8, 9, 3, 4, 5, 6, 7]
[8, 9, 3, 4, 5, 6, 7]

If you had stuck in values >= 16, you might get something like this:

Integer[] j = new Integer[] { 3, 4, 5, 6, 7, 8, 9, 16 };
...
[3, 4, 5, 6, 7, 8, 9, 16]
[16, 3, 4, 5, 6, 7, 8, 9]
[16, 3, 4, 5, 6, 7, 8, 9]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文