2 回答

TA贡献1858条经验 获得超8个赞
HashMap 不保证其迭代顺序。原则上(即规范允许)键的顺序是可能的,例如,从一个迭代到下一个迭代,即使映射的内容没有改变,或者迭代顺序为键与对应值的迭代顺序不同。
这在HashMap规范中有说明:
此类不保证地图的顺序;特别是,它不保证订单会随着时间的推移保持不变。
在实践中,如果 HashMap 的初始化和填充方式完全相同,则 HashMap 的迭代顺序从一次迭代到下一次,甚至从一次 JVM 调用到下一次都是稳定的。但是,应用程序依赖于此是不明智的。创建具有不同初始大小或加载因子的 HashMap 会影响迭代顺序,即使映射填充了相同的内容。HashMap 实现确实会不时更改,这也会影响迭代顺序。即使在 JDK 的补丁或错误修复版本中也会发生此类更改。不幸的是,历史表明,当迭代顺序发生变化时,应用程序会中断。因此,健壮的应用程序应该努力避免对 HashMap 迭代顺序产生任何依赖。
这在实践中很难做到。我知道 JDK 的一个(非公开)版本具有随机化 HashMap 的迭代顺序的测试模式。这可能有助于消除这种依赖关系。
如果您需要在迭代时关联 HashMap 的键和值,请获取 HashMap 的 entrySet() 并对其进行迭代。它提供映射条目(键值对),因此键和值之间的关系得以保留。
JDK 中的替代 Map 实现提供了良好定义的迭代顺序。TreeMap 和 ConcurrentSkipListMap 根据提供的比较方法对它们的条目进行排序。LinkedHashMap 提供基于插入顺序的迭代顺序。(它还提供了一种按访问顺序进行迭代的模式,这有时很有用,但其行为往往令人惊讶。)
请注意,Java 9 中引入的不可修改集合(Set.of、Map.of 等)提供了随机迭代顺序。JVM 的一次运行与下一次运行的顺序不同。这应该有助于应用程序避免对迭代顺序产生无意的依赖。

TA贡献1775条经验 获得超11个赞
让我们再看一下关于Map
合约中迭代顺序的 Java SE API 语言:
一些地图实现,如 TreeMap 类,对它们的顺序做出特定的保证;其他的,比如 HashMap 类,不这样做。
并且HashMap
:
此类不保证地图的顺序;特别是,它不保证订单会随着时间的推移保持不变。
由于明确指出 HashMap 迭代器没有顺序,因此不能假设即使在对同一方法的调用之间迭代也将是稳定的,更不用说在调用不同方法keySet()
和values()
.
有帮助的是,Map
有一种方法entrySet()
可以完全满足您的需要:它以配对键和值的方式迭代映射内容。这是在您需要依赖该对的两个部分时使用的方法。
随着对 Java 许可的更改现在生效,那些认为他们可能总是使用 Oracle 的 Java 实现的个人和组织现在正在寻找替代实现。依赖单一实现的不成文细节是极其危险的,现在比甲骨文的许可和定价变化之前更是如此。
添加回答
举报