由于规范不保证集合和映射的任何遍历/迭代顺序,所以这是完全可以接受的。事实上,代码不能依赖于实现特定的细节,而是要依赖于规范。
我知道在今天的JDK 8中,如果我有一个i.e.
HashSet
并执行以下操作(来自链接的答案):Set<String> wordSet = new HashSet<>(Arrays.asList("just", "a", "test"));
System.out.println(wordSet);
for (int i = 0; i < 100; i++) {
wordSet.add("" + i);
}
for (int i = 0; i < 100; i++) {
wordSet.remove("" + i);
}
System.out.println(wordSet);
那么,元素的迭代顺序将会改变,两个输出结果也会不同。这是因为向集合中添加和删除100个元素会改变HashSet
的内部容量并重新哈希元素。这是完全有效的行为。我在这里不讨论这个。
然而,在JDK9中,如果我这样做:
Set<String> set = Set.of("just", "a", "test");
System.out.println(set);
在另一个JVM实例中运行相同的代码时,输出可能会不同,因为引入了随机化。
到目前为止,我找到了这个优秀的YouTube视频(第44:55分钟),在视频中Stuart Marks说这种随机化的一种动机是:
人们编写应用程序时,可能会无意中依赖于迭代顺序。因此,迭代顺序是一个很大的问题,我认为有很多代码依赖于迭代顺序,但这些依赖尚未被发现。因此,我们的答复是在新集合中故意随机迭代顺序,包括
Set
和Map
。因此,以前集合的迭代顺序是不可预测但稳定的,而现在是可预测的不可预测的。每次JVM启动时,我们都会获得一个随机数,并将其作为种子值与哈希值混合。因此,如果您运行初始化集并按任意顺序打印元素的程序,则会得到一个答案,然后,如果再次调用JVM并运行相同的程序,则元素集通常会以不同的顺序出现。因此,这里的想法是如果您的代码存在迭代顺序依赖关系,那么过去发生的情况是新的JDK版本发布,您测试代码并且需要花费几个小时来跟踪迭代顺序的某些更改。这意味着该代码中存在依赖于迭代顺序的错误。现在,如果您更经常地变化迭代顺序,例如每次JVM调用,那么我们希望这种奇怪的行为会更频繁地表现出来,并且实际上我们希望在测试时...因此,动机是清晰的,并且很明显这种随机化只会影响新的不可变集合和映射。
我的问题是:是否存在其他的动机以进行这种随机化,它有什么优势?
HashMap
的顺序。 - Eugene