什么导致iterator()对java.util.HashSet和HashMap.keySet()类的稍微不可预知的排序? [英] What causes the slightly unpredictable ordering of the iterator() for the java.util.HashSet and HashMap.keySet() classes?

查看:138
本文介绍了什么导致iterator()对java.util.HashSet和HashMap.keySet()类的稍微不可预知的排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

六年前,我花了几天的时间试图寻找我的完美确定性框架随机响应的地方。在仔细追逐整个框架后,确保它全部使用了Random的相同实例,然后我继续追逐单步执行代码。这是高度重复的自我调用代码。更糟糕的是,这个该死的效果只会在大量迭代完成后才会显现出来。 +6小时后,当我在javadoc中为HashSet.iterator()发现了一行时,我终于终于明白了,表明它不保证它返回元素的顺序。然后我通过我的整个代码库并用LinkedHashSet替换了HashSet的所有实例。低调,我的框架突然出现在确定性的生活中! ARGH!



我现在刚刚经历了同样的FREAKIN效应,至少这次只有3个小时。无论出于什么原因,我都忽略了HashMap碰巧为它的keySet()具有相同的方式的细节。



这个主题是一个SO线程,虽然讨论从不完全解答我的问题: HashSet的迭代次序



所以,我很好奇为什么会发生这种情况。考虑到这两次,我有一个巨大的单线程Java应用程序通过完全相同的实例化/插入空间,在同一台计算机上具有完全相同的JVM参数(多个来自同一个批处理文件的运行),几乎没有其他任何运行,可能干扰JVM,使得HashSet和HashMap在经过大量迭代之后会表现出不可预测的行为(不像javadoc所说的不依赖于订单而不一致)?

任何想法这来自源代码(在java.util中实现这些类)或者从您对JVM的了解(也许某些GC影响内部java类在分配内部内存空间时获得非归零内存)?

解决方案

我之前触及过这个命令,但命令并不重要,但确实影响了结果。



Java的多线程特性意味着使用完全相同的输入重复运行可能会受到影响(例如)分配一个新的内存块需要多长时间,有时可能需要将内存分页到磁盘,而在其他时间则不需要。其他一些不使用该页面的线程可能会继续执行,并且在考虑到System对象时,最终可能会创建不同的对象创建顺序。



这会影响 Object.hashCode()在JVM的不同运行中的等效对象的结果。



对于我来说,我决定添加使用 LinkedHashMap 的小开销,以便能够重现我正在运行的测试的结果。


Six years ago, I burned several days trying to hunt down where my perfectly deterministic framework was responding randomly. After meticulously chasing the entire framework ensuring that it was all using the same instance of Random, I then kept chasing by single stepping code. It was highly repetitive iterative self-calling code. Worse, the damn effect would only show up after a huge number of iterations were completed. And after +6 hours, I was finally at wits end when I discovered a line in the javadoc for HashSet.iterator() indicating it doesn't guarantee the order in which it will return elements. I then went through my entire code base and replaced all instances of HashSet with LinkedHashSet. And low-and-behold, my framework sprang right to deterministic life! ARGH!

I have now just experienced this same FREAKIN affect, again (at least it was only 3 hours this time). For whatever reason, I missed the small detail that HashMap happens to BEHAVE THE SAME WAY for its keySet().

Here's an SO thread on this subject, although the discussion never quite answers my question: Iteration order of HashSet

So, I am curious as to why this might occur. Given both times I had a huge single threaded java application crawling through exactly the same instantiation/insertion space with exactly the same JVM parameters (multiple runs from the same batch file) on the same computer with almost nothing else running, what could possibly perturb the JVM such that HashSet and HashMap would, after an enormous number of iterations, behave unpredictably (not inconsistenly as the javadoc says not to depend upon the order)?

Any ideas around this from either the source code (implementation of these classes in java.util) or from your knowledge of the JVM (perhaps some GC affect where internal java classes get non-zeroed memory when allocating internal memory spaces)?

解决方案

I've struck this before, where the order wasn't important, but did affect the results.

The multi-threaded nature of Java means that repeated runs with exactly the same inputs can be affected by slight timing differences in (for example) how long it takes to allocate a new block of memory, which might sometimes require paging out to disk the previous contents, and at other times that isn't needed. Some other thread not using that page may proceed, and you could end up with a different order of object creation, when System objects are taken into account.

That can affect the Object.hashCode() result for the equivalent object in different runs of the JVM.

For me, I decided to add the small overhead of using a LinkedHashMap, in order to be able to reproduce the results of the tests I was running.

这篇关于什么导致iterator()对java.util.HashSet和HashMap.keySet()类的稍微不可预知的排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆