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

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

问题描述

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



我想迭代这个地图,并修改一些数据POJO。



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



这不行,因为您不要在迭代时修改地图(方法是同步的,但仍然出现ConcurrentModificationException)



我的问题是,如果我需要迭代地图并更改值,可以使用哪些最佳做法/方法?要创建一个单独的地图,并建立起来,我去,然后返回副本?

解决方案

两个选项: / strong>



选项1




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


您是否更改了 em>到POJO?例如,进入点是否完全是其他的东西?因为如果没有,那么就没有必要把它从地图上删除,你可以改变它。



选项2



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



示例:

  Map< String,String>地图; 
Map.Entry< String,String>条目;
迭代器< Map.Entry< String,String>>它;

//创建地图
map = new HashMap< String,String>();
map.put(one,uno);
map.put(two,due);
map.put(three,tre);

//通过条目迭代,更改其中一个
it = map.entrySet()。iterator();
while(it.hasNext())
{
entry = it.next();
System.out.println(Visiting+ entry.getKey());
if(entry.getKey()。equals(two))
{
System.out.println(修改它);
entry.setValue(DUE);
}
}

//显示结果
it = map.entrySet()。iterator();
while(it.hasNext())
{
entry = it.next();
System.out.println(entry.getKey()+=+ entry.getValue());
}

输出(没有特定的顺序)是:


访问两个

修改

访问一个

访问三个
< br> two = DUE

one = uno

three = tre


没有任何修改例外。你可能想要同步这个,以防其他的东西也看着/弄脏那个条目。


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

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

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

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?

解决方案

Two options:

Option 1

The current code I've inherited removes the given entry, and adds it back in after making some changes to the 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.

Option 2

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.

Example:

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:

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天全站免登陆