且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

迭代地图和更改值时如何避免 ConcurrentModificationException?

更新时间:2022-03-12 23:49:31

两个选项:

我继承的当前代码删除了给定的条目,并在对 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.