【问题标题】:Is map/collection order stable between calls?调用之间的地图/收集顺序是否稳定?
【发布时间】:2010-06-01 22:48:00
【问题描述】:

如果我有一个哈希映射并反复迭代对象,我不能保证每次调用的顺序都相同,这是否正确?例如,以下是否可以打印两行彼此不同的行:

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);

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

【问题讨论】:

    标签: java collections iteration


    【解决方案1】:

    MapSet 的合约不保证迭代顺序,但 SortedSetSortedMap(由TreeMapTreeSet 实现)的合约可以。

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

    【讨论】:

      【解决方案2】:

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

      话虽如此,但代码可能会打印两次相同的内容,但这并不能保证。

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          【解决方案4】:

          我认为现有的任何答案都不能完全符合您的要求。当然,具有某些内容的 HashMap 可能不会以与具有相同内容、不同 VM 调用或在不同 JDK 版本上运行的不同方式相同的方式进行迭代,等等。但你只是在问那个确切的实例,如果未修改,将以与自身相同的方式进行迭代。

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

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

          【讨论】:

            【解决方案5】:

            虽然库规范不保证随着时间的推移顺序保持不变,但只要底层数据结构(即实现哈希表的数组)没有改变,它可能会保持不变。所以只要你不从哈希表中插入或删除项目,假设进入顺序不会改变也不是没有道理的。

            查看HashMap 的典型实现表明情况确实如此,例如: http://www.docjar.com/html/api/java/util/HashMap.java.html

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2010-09-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-10-06
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多