迭代地图和更改值时如何避免 ConcurrentModificationException? [英] How to avoid ConcurrentModificationException when iterating over a map and changing values?

查看:33
本文介绍了迭代地图和更改值时如何避免 ConcurrentModificationException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含一些键(字符串)和值(POJO)的映射

I've got a map containing some keys (Strings) and values (POJOs)

我想遍历此映射并更改 POJO 中的一些数据.

I want to iterate through this map and alter some of the data in the POJO.

我继承的当前代码删除了给定的条目,并在对 POJO 进行了一些更改后重新添加.

The current code I've inherited removes the given entry, and adds it back in after making some changes to the POJO.

这行不通,因为您不应该在遍历地图时修改地图(方法已同步,但仍会出现 ConcurrentModificationException)

This doesn't work well, since you shouldn't be modifying a map whilst your iterating through it (method is synchronised, but ConcurrentModificationException still appears)

我的问题是,如果我需要迭代地图并更改值,那么我可以使用哪些最佳实践/方法?要创建一个单独的地图并在我进行时构建它,然后返回副本?

My question is, if I need to iterate over a map and change values, what are the best practices/methods I can use for doing so? To create a separate map and build that up as I go, then return the copy?

推荐答案

两个选项:

我继承的当前代码删除了给定的条目,并在对 POJO 进行了一些更改后重新添加.

The current code I've inherited removes the given entry, and adds it back in after making some changes to the POJO.

您是否要将引用更改为 POJO?例如,所以入口完全指向其他东西?因为如果没有,根本不需要从地图中删除它,您只需更改它即可.

Are you changing the reference to the POJO? E.g., so the entry points to something else entirely? Because if not, there's no need to remove it from the map at all, you can just change it.

如果您确实需要实际更改对 POJO 的引用(例如,条目的值),您仍然可以通过迭代 Map.Entry 来自 entrySet() 的实例.您可以在条目上使用 setValue,它不会修改您要迭代的内容.

If you do need to actually change the reference to the POJO (e.g., the value of the entry), you can still do that in place by iterating over the Map.Entry instances from entrySet(). You can use setValue on the entry, which doesn't modify what you're iterating over.

示例:

Map<String,String>                  map;
Map.Entry<String,String>            entry;
Iterator<Map.Entry<String,String>>  it;

// Create the map
map = new HashMap<String,String>();
map.put("one", "uno");
map.put("two", "due");
map.put("three", "tre");

// Iterate through the entries, changing one of them
it = map.entrySet().iterator();
while (it.hasNext())
{
    entry = it.next();
    System.out.println("Visiting " + entry.getKey());
    if (entry.getKey().equals("two"))
    {
        System.out.println("Modifying it");
        entry.setValue("DUE");
    }
}

// Show the result
it = map.entrySet().iterator();
while (it.hasNext())
{
    entry = it.next();
    System.out.println(entry.getKey() + "=" + entry.getValue());
}

输出(无特定顺序)是:

The output (in no particular order) is:

拜访两个
修改它
拜访一位
参观三
二=到期
一=uno
三=tre

Visiting two
Modifying it
Visiting one
Visiting three
two=DUE
one=uno
three=tre

...没有任何修改异常.您可能希望同步它,以防其他东西也在查看/破坏该条目.

...without any modification exception. You will probably want to synchronize this in case something else is also looking at / mucking with that entry.

这篇关于迭代地图和更改值时如何避免 ConcurrentModificationException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆