当前位置: 首页 > 知识库问答 >
问题:

当独立迭代时,无序散列映射中的键和值是否对齐?

慕皓君
2023-03-14

我看到过与这个主题相关的答案,但我想知道是否有人有过这样的例子,即从hash map派生的键集和值列表将以不同的顺序显示键和值。我知道条目本身在散列映射中可以有未定义的顺序,但键和值的列表是否会彼此顺序不一致?

下面是一个简短的片段以供澄清:

public class App {
    public static void main(String[] args) {
        Map<String,String> stateCapitols = new HashMap<>();
        stateCapitols.put("AL", "Montgomery");
        stateCapitols.put("AK", "Juneau");
        stateCapitols.put("CO", "Denver");
        stateCapitols.put("FL", "Tallahassee");
        stateCapitols.put("Indiana", "Indianapolis");

        stateCapitols.keySet().stream().forEach(System.out::println);
        System.out.println();
        stateCapitols.values().stream().forEach(System.out::println);
    }
}

在上述示例中,AL是否会以任何方式出现在丹佛(或任何其他值)相同的位置?

共有2个答案

薛墨一
2023-03-14

HashMap不保证其迭代顺序。原则上(也就是说,规范允许)键的顺序可以从一次迭代更改到下一次迭代,即使映射的内容没有更改,或者键的迭代顺序可以不同于相应值的迭代顺序。

这在HashMap规范中说明:

这个类不保证地图的顺序;特别是,它不能保证随着时间的推移,订单将保持不变。

实际上,如果HashMap的初始化和填充方式完全相同,HashMap的迭代顺序从一次迭代到下一次,甚至从一次JVM调用到下一次都是稳定的。然而,应用程序依赖于此是不明智的。创建具有不同初始大小或负载因子的HashMap会影响迭代顺序,即使地图填充了相同的内容。HashMap实现确实会不时更改,这也会影响迭代顺序。即使在JDK的补丁或错误修复版本中也会发生这样的更改。不幸的是,历史表明,当迭代顺序改变时,应用程序会中断。因此,健壮的应用程序应该努力避免对HashMap迭代顺序产生任何依赖。

这在实践中很难做到。我知道JDK的一个(非公开)版本有一种测试模式,可以随机化哈希映射的迭代顺序。这可能有助于消除这种依赖关系。

如果需要在迭代HashMap时关联其键和值,请获取HashMap的entrySet()并进行迭代。它提供了映射条目(键值对),因此保留了键和值之间的关系。

JDK中的替代映射实现提供了定义良好的迭代顺序。TreeMap和ConcurrentSkipListMap根据提供的比较方法对其条目进行排序。LinkedHashMap根据插入顺序提供迭代顺序。(它还提供了一种模式,其中迭代是按访问顺序进行的,这有时很有用,但其行为往往令人惊讶。)

请注意,Java9中引入的不可修改集合(Set.of、Map.of等)提供了随机迭代顺序。JVM每次运行的顺序都会有所不同。这将帮助应用程序避免对迭代顺序产生无意的依赖。

韦鸣
2023-03-14

让我们再次看看Java SE API语言,它与Map合同中的迭代顺序有关:

一些map实现,比如TreeMap类,对它们的顺序做出了具体的保证;其他的,比如HashMap类,则没有。

HashMap

这个类不保证地图的顺序;特别是,它不能保证随着时间的推移,订单将保持不变。

由于明确说明HashMap迭代器没有顺序,因此不能假设迭代即使在调用同一个方法之间也是稳定的,更不用说在调用不同的方法keySet()values()之间了。

有用的是,Map有一个方法entrySet(),它完全满足您的需要:它以对键和值进行配对的方式对map内容进行迭代。在您需要依赖这两个部分的任何时候,都可以使用它。

随着Java许可的改变现在生效,那些认为他们可能会一直使用甲骨文Java实现的人和组织现在正在寻找替代实现。依赖单一实现的不成文细节是极其危险的,现在比甲骨文许可和定价改变之前更加危险。

 类似资料:
  • 我有我创建的地图的地图 我尝试在第二个映射中迭代键的值。 所以它可以是这样的: key1->keya->value1 -------->键->值2 -------->键->值4 -------->KeyC->value1 我想继续多久就继续多久。 因此,我有,并尝试使用名为的值变量和增量计数器if来循环中的所有值 我不知道如何获得。我试着这样做 但这给了我信笺。 如果我执行,它会给出我想要的正确值

  • 问题内容: 我需要一个Map,它可以 按其值 的降序进行迭代。是否有像Apache Commons或Guava这样的标准库提供这种地图? 问题答案: 我会用番石榴来做到这一点,如下所示:

  • 我在迭代一个对象内的列表时遇到了一个问题,该对象内嵌在另一个映射中。我的目标是迭代这个列表并生成一个映射 ,我希望使用streams和lamdas来实现这一点。 我在上面看到了,我需要通过迭代FolderBo中的elementList从elementBo创建一个带有map 的映射。folderBo本身就在Modelbo的地图内。

  • 我有如下所示的电影实体。我需要根据电影代码对所有实体进行分组,实现如下。现在我需要按扫描日期时间按降序{latest first}对哈希映射的值进行排序。我可以在按流程分组时执行此操作。这里的关键是电影实体的列表。

  • 假设我们有一个键-值映射的数据结构,其中键本身也是一个键-值映射。例如: 现在,假设我们要查询此映射中与键的某个键值子集匹配的所有顶级键/值。示例: 我们的查询是“给我所有key值,其中key包含,它将返回第一个和第三个值将返回所有同时具有和的键值,生成第二个值。显然,我们可以在每一个查询的完整地图中进行搜索,但我正在寻找比这更高效的方法。 我四处查看了一下,但是找不到一个高效、易用的C解决方案。

  • 问题内容: 使用Python 2.7。我有一本字典,其中以球队名称为键,对每支球队得分并允许的奔跑次数作为值列表: 我希望能够将字典输入一个函数并遍历每个团队(键)。 这是我正在使用的代码。现在,我只能逐队参加。我将如何遍历每个团队并为每个团队打印预期的win_percentage? 谢谢你的帮助。 问题答案: 您有几种选择可以遍历字典。 如果迭代字典本身(),则将迭代字典的键。当使用for循环进