我有一些使用标准Java集合的代码:arrays,ArrayDeques,HashMaps,Lists,HashSets。
我的代码应该是确定性的:所有元素的哈希码,集合的初始内容等预计仅取决于输入数据。代码的最终输出是从某个HashMap的keySet()
生成的。
我注意到生成的keySet中元素的顺序有时会随着运行而变化。这是什么意思?
这与Windows 7 x64上的JDK 1.7.0_60,x86完全一致。 据称,JDK 1.8.0_05不会发生这种情况(或很少发生)。 此外,在上述JDK之间切换时,生成的keySet中的元素顺序(以及处理数据项的整体顺序)也会发生变化。
我怀疑,这是HashSet的一些功能,但无法将其跟踪到特定的代码行。
UPD 1 我真的不需要确定性集合,我知道HashSet不提供任何保证。我只是想找到非确定性行为的原因。如果它在库代码中 - 很好。但如果它在我的代码中 - 我可能不得不修复它。因此问题。
UPD 2 当然,我在发布问题后立即找到答案。就在1.7的HashMap.java开头:
/**
* A randomizing value associated with this instance that is applied to
* hash code of keys to make hash collisions harder to find. If 0 then
* alternative hashing is disabled.
*/
transient int hashSeed = 0;
在1.8中,这种随机化似乎不再存在。
答案 0 :(得分:5)
它不保证集合的迭代顺序;特别是,它不保证订单会随着时间的推移保持不变。
答案 1 :(得分:2)
如果你需要一个稳定的有序HashSet,那么你应该按照javadoc使用LinkedHashSet
,
Set接口的哈希表和链表实现,具有可预测的迭代顺序
根据HashSet
javadoc,
...不保证集合
的迭代顺序
答案 2 :(得分:0)
只需在此处复制已包含在问题中的内容。快速浏览一下消息来源表明,在1.7中,HashMap确实具有非确定性行为,并且每个实例都使用一些随机值来对元素的散列进行种子处理。在1.8中,实现已经改变,随机化似乎不再存在。