java – 关于不可变集和映射的JDK9随机化
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java – 关于不可变集和映射的JDK9随机化,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5416字,纯文字阅读大概需要8分钟。
内容图文
![java – 关于不可变集和映射的JDK9随机化](/upload/InfoBanner/zyjiaocheng/709/05554f0b16d4401d82b48fd0435d0397.jpg)
阅读this question和the answer given by Eugene,我发现JDK9不可变集和映射将引入一个会影响其遍历的随机源.这意味着迭代顺序确实是随机的,至少在JVM的不同运行中是这样.
由于规范不保证集合和映射的任何遍历/迭代顺序,这绝对没问题.实际上,代码绝不能依赖于特定于实现的细节,而是依赖于规范.
我知道今天,使用JDK 8,如果我有一个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的另一个实例中,我运行相同的代码,输出可能不同,因为已经引入了随机化.
到目前为止,我已经找到了这个优秀的video in youtube (minute 44:55),其中Stuart Marks说这种随机化的一个动机是:
(…) that people write applications that have inadvertent dependencies on iteration order. (…) So, anyway, iteration order is a big deal and I think there’s a lot of code out there that has latent dependencies on iteration order that has not been discovered yet. (…) So, our response to this is to deliberately randomize the iteration order in
Set
andMap
in the new collections. So whereas before the iteration order of collections was unpredictable but stable, these are predictably unpredictable. So every time the JVM starts up, we get a random number and we use that at as a seed value that gets mixed in with the hash values. So, if you run a program that initializes a set and then prints out the elements in any order, you get an answer, and then, if you invoke the JVM again and run that same program, the set of elements usually would come out in a different order. So, the idea here is that (…) if there are iteration order dependencies in your code, what used to happen in the past, is a new JDK release came out and you test your code and (…) it’d take hours of debugging to trace it down to some kind of change in iteration order. What that meant was there was a bug in that code that depended on the iteration order. Now, if you vary the iteration order more often, like every JVM invocation, then (we hope) that weird behavior will manifest itself more frequently, and in fact we hope while you’re doing testing…
因此,动机很明确,而且很明显,这种随机化只会影响新的不可变集和映射.
我的问题是:这种随机化还有其他动机吗?它有什么优势?
解决方法:
事实证明,随机迭代顺序还有另一个原因.这不是一个大秘密或任何东西.我以为我已经在那次谈话中解释过了,但也许不是.我可能在OpenJDK邮件列表或者内部讨论中提到过它.
在任何情况下,随机迭代顺序的另一个原因是为将来的实现更改保留灵活性.
事实证明这比大多数人想象的要大.从历史上看,HashSet和HashMap从未指定过特定的迭代顺序.但是,有时需要实现更改,提高性能或修复错误.对迭代顺序的任何更改都会从用户中产生很多瑕疵.多年来,许多阻力都在改变迭代顺序,这使得维护HashMap变得更加困难.
要了解这是一个问题,请考虑一系列不同的策略来管理迭代顺序的稳定性:
>指定迭代顺序,并坚持下去.
>不指定迭代顺序,但隐式地保持迭代顺序稳定.
>不指定迭代顺序,但尽可能少地更改迭代顺序.
>经常更改迭代顺序,例如,在更新版本中.
>更频繁地更改迭代顺序,例如,从JVM的一次运行到下一次运行.
>更频繁地更改迭代顺序,例如,从一次迭代到下一次迭代.
在JDK 1.2中引入集合时,未指定HashMap迭代顺序. LinkedHashMap以较高的成本提供了稳定的迭代顺序.如果您不需要稳定的迭代订单,则不必为此付费.这排除了#1和#2.
对于接下来的几个版本,我们试图保持迭代顺序稳定,即使规范允许它更改.代码中断时没有人喜欢它,并且告诉客户他的代码被破坏是非常不愉快的,因为它取决于迭代顺序.
所以我们最终得到了政策#3,尽可能保持迭代顺序尽可能稳定,尽管它确实不时发生变化.例如,我们在JDK 7u6(JDK-7118743为code review)和JDK 8(JEP 180)中的树箱中引入了替代散列,并且在某些情况下都改变了HashMap迭代顺序.在早期版本中,订购也改变了几次.有人做了一些考古学,发现每个主要JDK版本的迭代顺序平均改变了一次.
这是所有可能世界中最糟糕的.主要版本每两年才发生一次.当一个人出来时,每个人的代码都会破裂.人们会修复他们的代码,并且我们承诺永远不会再次改变迭代顺序.几年过去了,编写的新代码无意中依赖于迭代顺序.然后我们将推出另一个改变迭代顺序的主要版本,这将再次破坏每个人的代码.这个循环将重新开始.
我想避免为新集合重复这个循环.我没有尽可能保持迭代顺序稳定,而是采取了尽可能频繁地改变它的政策.最初,每次迭代都会更改顺序,但这会带来一些开销.最终,我们每次JVM调用都确定了一次.每个表探测器的成本是32位XOR操作,我认为这很便宜.
在某种程度上,这是关于“强化”应用程序代码.如果更改迭代顺序会破坏代码,那么更频繁地破坏该代码将导致它产生那种破坏的阻力.当然,代码本身并没有变得更强大;它需要更多的开发人员才能实现这一目标.人们会非常合理地抱怨不得不做这项额外的工作.
但是,应用程序代码的“强化”在某种意义上是继承保留更改实现的自由的另一个目标.保留HashMap的迭代顺序使得维护更加困难.新集合中的随机迭代顺序意味着我们在修改它们时不必担心保留迭代顺序,因此它们更易于维护和增强.
例如,当前的实现(Java 9,pre-GA,2017年7月)有三个基于字段的Set(Set0,Set1和Set2)实现和一个基于数组的实现(SetN),它使用一个简单的闭合散列和线性探测方案.将来,我们可能希望添加一个Set3实现,该实现在三个字段中包含三个元素.或者,我们可能希望将SetN的冲突解决策略从线性探测更改为更复杂的策略.如果我们不必处理保留迭代顺序,即使在次要版本中,我们也可以完全重构实现.
总之,权衡是应用程序开发人员必须做更多的工作,以确保他们的代码抵制迭代顺序更改的破坏.这可能是他们在某些时候必须使用HashMap做的工作.由此获得的是JDK提供更多机会和空间效率的机会,每个人都可以从中受益.
内容总结
以上是互联网集市为您收集整理的java – 关于不可变集和映射的JDK9随机化全部内容,希望文章能够帮你解决java – 关于不可变集和映射的JDK9随机化所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。