实际上Set不是有序的。我只是创建集合并插入数字5,2,10
Wen打印在控制台中,打印为2,5,10
。
为什么set没有订购?
答案 0 :(得分:2)
这是因为这会加快查询某个元素是否属于集合的查询。
不同之处在于无法保证此行为。保持为快速查找排序的小集合可能是有益的,但是一旦达到一定数量的元素就切换到基于散列的实现,此时元素将突然按哈希值排序。
答案 1 :(得分:0)
Set
是interface
,但它有多个实现。 HashSet
无法保证您的广告订单(未订购)。 LinkedHashSet
保留了广告订单,TreeSet
为您提供了排序set
(排序集)。
然后您将5,2,10
插入HashSet
,无法保证订单相同。
答案 2 :(得分:0)
Set
只是一个界面,假设您正在谈论HashSet
(因为它发生了这种情况),它并没有对它们进行排序。例如:
HashSet<Integer> set = new HashSet<Integer>();
set.add(1);
set.add(16);
System.out.println(set);
输出
[16, 1]
这是因为HashSet
使用hashcode
函数来计算项目将以类似数组的结构存储的索引。这样,由于hashcode
永远不会改变,它可以从正确的索引中提取元素,再次计算hashcode
并检查该索引处的单元格。
hashcode
函数将大多数类转换为整数:
System.out.println(new Integer(1).hashCode()); # 1
System.out.println(new Integer(1000).hashCode()); # 1000
System.out.println("Hello".hashCode()); # 69609650
每个类都可以定义自己的方式来计算哈希码,Integer
返回自己。
正如你所看到的那样,数字很快就会变大,我们不希望有一个带有 1000 单元的数组只是为了保存两个整数。
为了避免这个问题,我们可以创建一个包含n
元素的数组,然后使用哈希码的剩余部分除以n
作为索引。 / p>
例如,如果我们想在 16 元素的数组中找到1000
的索引:
System.out.println(new Integer(1000).hashCode() % 16); # 8
因此我们的字典会知道整数1000
位于索引 8 。这就是HashSet
的实施方式。
那么,为什么[16, 1]
没有订购?这是因为HashSet
是使用 16 元素创建的,因为它们在开始时的容量(当没有不同的指定时),并根据需要增长(更多关于此here)。
让我们计算索引,将key = 2
和key = 9
的数据存储在n = 8
的字典中:
System.out.println(new Integer(1).hashCode() % 16); # 1
System.out.println(new Integer(16).hashCode() % 16); # 0
这意味着包含字典数据的数组将是:
| index | value |
|-------|-------|
| 0 | 16 |
| 1 | 1 |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
对其进行迭代后,订单将是此代表中显示的顺序,因此16
将在1
之前。
答案 3 :(得分:0)
Set是界面。它仅表示避免集合的重复实体。
HashSet内部使用Hashmap。通常hashmap使用hashcode。所以它不会以有序的方式返回。如果您需要广告订单,则会使用LinkedHashMap。
答案 4 :(得分:-1)
Set
只是一个界面。订购将取决于实施。例如,TreeSet
是Set
的有序实现。