java - 为什么这个 HashSet 在打印时看起来是排序的?
问题描述
Set<Integer> s = new HashSet<Integer>();
s.add(77);
s.add(0);
s.add(1);
System.out.println(s);
TreeSet<Integer> s1 = new TreeSet<Integer>();
s1.add(77);
s1.add(0);
s1.add(1);
System.out.println(s1);
输出:
s = [0, 1, 77]
s1= [0, 1, 77]
根据教程点页面上的定义
Set 是一组没有重复元素的通用值。TreeSet 是对元素进行排序的集合。
为什么两者的输出都是s
排序s1
的?我期望只s1
对 ' 的输出进行排序。
解决方案
你是对的,s1
因为它是排序的TreeSet
,但s
不是真正排序的。如果您向 中添加更多元素s
,您会看到一些奇怪的事情发生。
After adding 32, 12, 13, and 14
[0, 32, 1, 12, 77, 13, 14]
所以现在你看到它有点有序,但不是真的。原因是HashSet
默认容量为 16,以后会随着需要的增加而增长。因此,当您向其中添加一个元素时,想象它采用该元素的哈希码,模 16,以便它适合 16 个存储桶的内部“列表”。由于 an 的哈希码Integer
是它表示的 int,我们可以假装它所做的只是 do (the element to be added) % 16
。
因此,当您添加 0、1 和 77 时,它可能在内部看起来像这样:
Bucket Elements
0 0
1 1
2
3
4
5
...
13 77 (77 % 16 is 13, so it's placed here)
14
15
16
然后我们添加 32。32 % 16 为 0,但我们已经0
在第一个桶中。幸运的是,为了防止这样的冲突,HashSet
s 使用链表而不是单个元素,因此我们只需将 32 附加到包含 0 的链表。
Bucket Elements
0 0 -> 32
1 1
2
3
4
5
...
13 77
14
15
16
对于 12、13 和 14,它的工作方式也相同:
Bucket Elements
0 0 -> 32
1 1
2
3
4
5
...
12 12
13 77 -> 13
14 14
15
16
如果您按顺序遍历存储桶,打印该存储桶中的每个链表,您会得到[0, 32, 1, 12, 77, 13, 14]
看它运行
推荐阅读
- r - R如何在循环中提取变量,匹配两个条件?
- elasticsearch - 如何从 Logstash 获取消息数组中的字段?
- json - 如何从 QT 中的 JSON 文件中读取特定记录
- vb6 - How do I parse/split the second specific character from the right to left?
- javascript - 如何在 JavaScript 中声明具有对象数组的对象?
- git - git-add 能做什么,而 git update-index 不能?
- android - 通知声音在第二次尝试中不起作用 - Android Studio
- reactjs - 使用反应路由器路由到不同组件以获得类似路由
- perl - 用 tr 转义正斜杠
- ssl - 设置 sslmode=verify-ca 后无法验证主机名