迭代时允许对Map进行哪些基本操作?

假设我在Java中迭代一个Map …我不清楚在迭代过程中我能对Map进行什么操作。 我想我在Javadoc中为Iterator接口删除方法的这个警告感到困惑:

[…]如果在迭代正在进行中以除调用此方法之外的任何方式修改基础集合,则未指定迭代器的行为。

我确信我可以毫无问题地调用remove方法。 但是在迭代Map集合时,我可以:

  1. 使用Map类put方法更改与键关联的值(使用现有键放置)?

  2. 使用Map类put方法添加一个新条目(使用新密钥放置)?

  3. 使用Map类删除方法删除条目?

我的猜测是我可以安全地做#1(放到现有密钥)但不安全做#2或#3。

提前感谢您对此的任何澄清。

您可以使用Iterator.remove() ,如果使用entrySet迭代器(Map.Entry的),您可以使用Map.Entry.setValue() 。 任何其他和所有的赌注都是关闭的 – 您不应该直接更改地图,并且某些地图不允许上述方法中的任何一个或两个。

具体而言,不允许使用您的(1),(2)和(3)。

可以通过Map对象设置现有密钥的值,但Set.iterator()文档特别排除了它,它将是特定于实现的:

如果在对集合进行迭代时修改了映射(除非通过迭代器自己的remove操作,或者通过迭代器返回的映射条目上的setValue操作),迭代的结果是未定义的 。 (重点补充)

如果你看一下HashMap类,你会看到一个名为’modCount’的字段。 这是地图在迭代期间修改的时间。 在迭代时增加modCount的任何方法都会导致它抛出ConcurrentModificationException。

也就是说,如果密钥已经存在,您可以将值放入映射中,使用新值有效地更新条目:

  Map test = new HashMap(); test.put("test", 1); for(String key : test.keySet()) { test.put(key, 2); // this works! } System.out.println(test); // will print "test->2" 

当您询问是否可以“安全地”执行这些操作时,您不必过于担心,因为HashMap会在遇到类似问题时立即抛出ConcurrentModificationException。 这些操作会很快失败; 他们不会让地图处于糟糕状态。

没有全球答案。 地图界面允许用户选择。 不幸的是,我认为jdk中的所有实现都使用了fail-fast实现(这里是fail-fast的定义,正如HashMap Javadoc中所述 ):

所有这个类的“集合视图方法”返回的迭代器都是快速失败的:如果在创建迭代器之后的任何时候对映射进行结构修改,除了通过迭代器自己的remove方法之外,迭代器将抛出ConcurrentModificationException。 。 因此,在并发修改的情况下,迭代器快速而干净地失败,而不是在未来的未确定时间冒任意,非确定性行为的风险。

通常,如果要在迭代时更改Map,则应使用迭代器的方法之一。 我实际上没有测试过看看#1是否会起作用,但其他人肯定不会。