【问题标题】:Java HashMap add new entry while iteratingJava HashMap 在迭代时添加新条目
【发布时间】:2015-01-03 08:52:50
【问题描述】:

在哈希映射中

map = new HashMap<String,String>();

it = map.entrySet().iterator();
while (it.hasNext())
{
    entry = it.next();
    it.remove(); //safely remove a entry
    entry.setValue("new value"); //safely update current value
    //how to put new entry set inside this map
    //map.put(s1,s2); it throws a concurrent access exception

}

当我尝试向映射添加新条目时,它会抛出 ConcurrentModificationException。对于删除和更新迭代器具有安全删除方法。如何在迭代时添加新条目?

【问题讨论】:

  • 创建一个新的Map&lt;String, String&gt; foo 实例并在那里设置所需的值。在您的流程结束时,使用 map = foo; 将此地图分配给您的旧地图。
  • 我想到了。没有其他直接的方法吧?
  • 您可以使用ConcurrentHashMap 来做到这一点,但这似乎有点矫枉过正。此外,这些清理任务不适合使用迭代器。

标签: java iterator concurrentmodification


【解决方案1】:

您需要考虑在迭代时将值放入 M​​ap 意味着什么。 HashMap 没有定义迭代其条目的顺序。因此,当您放置一个新条目时,该条目是否应该稍后由迭代器返回。行为的一致性很重要。但是,无论您决定采用哪种方式,当您将新值放入预先存在的键时,都会出现不一致的行为。如果密钥已经被迭代,那么更改将不会出现,并且如果密钥尚未由迭代器生成,则会出现。

解决此问题的一种简单方法是创建新键值对的临时 Map,并在迭代结束时将临时 Map 添加到主 Map。

Map<String,String> values = ...

Map<String,String> temp = new HashMap<>();
for (Entry<String,String> entry : values.entrySet()) {
    if ("some value".equals(entry.getValue()) {
        temp.put(entry.getValue(), "another value");
    }
}
values.putAll(temp);

【讨论】:

  • 并不总是需要一致的行为,尤其是概率算法。
【解决方案2】:

您需要在迭代集合时使用ConcurrentHashMap 添加元素。 HashMap 使用快速失败的迭代器,当迭代时更新集合时抛出 ConcurrentModificationException。而ConcurrentHashMap 使用故障安全迭代器,它基本上适用于底层集合的克隆,因此允许在迭代时进行修改。

【讨论】:

  • 我认为在这种情况下使用ConcurrentHashMap 可能是矫枉过正。
【解决方案3】:

怎么样:

map = new HashMap<String,String>();

it = map.entrySet().iterator();
while (it.hasNext())
{
    entry = it.next();
    entry.setValue("new value"); // update current value
}

我检查了 HashMap 实现,当更新这样的条目时,它不会更改其修改计数。我也认为没有理由不允许这样做。没有删除任何内容,没有添加任何内容,也没有更改任何键。

【讨论】:

    【解决方案4】:

    我所做的是用当前元素创建一个数组,然后遍历该数组:

    Feature[] initialFeatures = featureMap.values().toArray(new Feature[featureMap.values().size()]);
    
    for (Feature feature : initialFeatures)
    {/* Code that can safely add to the featureMap */}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-21
      • 1970-01-01
      • 2015-05-02
      • 2016-01-30
      • 2020-03-04
      • 1970-01-01
      • 1970-01-01
      • 2021-07-31
      相关资源
      最近更新 更多