呼叫之间的地图/收集顺序是否稳定?

时间:2010-06-01 22:48:01

标签: java collections iteration

如果我有一个哈希映射并重复遍历这些对象,那么我是否保证每次调用的顺序都相同?例如,以下打印两行彼此不同的行:

Map<String,Integer> map = new HashMap<String,Integer>()
  {{ put("a", 1); put("b", 2); put("c", 3); }};
System.out.println(map);
System.out.println(map);

这是集合和集合的情况吗?如果是这样,如果你必须以相同的顺序在同一个集合上迭代两次(不管是什么顺序),最好的方法是什么?我想转换成一个列表。

5 个答案:

答案 0 :(得分:7)

MapSet的合同不对迭代顺序做出任何保证,而是SortedSetSortedMap的合同(由TreeMap和{实现} {1}})做。

此外,即使非排序实现通常也具有确定性,并且每个特定实例都具有可重复的迭代顺序,只要它不以任何方式进行修改即可。但是,这是一个实现细节,不应该依赖它。

答案 1 :(得分:3)

你是对的,不保证地图的顺序。如果您需要在电话之间保持相同的顺序,您可能希望查看TreeMap之类的内容。

话虽如此,代码可能会打印出两次同样的东西,但这并不能保证。

答案 2 :(得分:3)

使用HashMap时,无法保证迭代次序在每次迭代时都是相同的。

相反,请考虑LinkedHashMap,,它是具有可预测迭代顺序的哈希表。

答案 3 :(得分:2)

我认为任何现有的答案都不能完全说明你所询问的内容。当然,具有某些内容的HashMap可能不会以与具有相同内容的不同内容相同的方式进行迭代,或者在不同的VM调用中进行迭代,或者在不同的JDK版本上运行等等。但是,您只是询问是否确切的实例,如果未经修改,将以与相同的方式迭代。

这是事实上的规范的一个很好的例子。确实,在规范的字母中没有出现这种情况。但是,每个JDK集合都以这种方式运行(在访问顺序的LinkedHashMap的情况下,您每次都会迭代一次)。而且很难想象一个没有这个属性的集合实现。我已经实现并审查了许多集合,只有一次我认为每次都会以不同方式迭代的集合;这是一个非常奇怪的案例,我最终抛弃了整个想法,因为每次迭代的方式都太奇怪了(也就是说,违反了我提到的事实上的规范)。

所以我说继续前进并依赖它。这不是依赖于您想要的任何旧的未指定行为的一揽子建议。但在这种情况下,它不会伤害你。

答案 4 :(得分:1)

虽然库规范不保证顺序随时间保持不变,但只要基础数据结构(即实现哈希表的数组)不被改变,它就可能是相同的。因此,只要您不在哈希表中插入或删除项目,假设输入顺序不会改变就不合理。

查看HashMap的典型实现显示了这种情况,例如: http://www.docjar.com/html/api/java/util/HashMap.java.html

话虽如此,但这不是你的代码应该依赖的东西。