Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
221 views
in Technique[技术] by (71.8m points)

java - How to avoid ConcurrentModificationException when iterating over a map and changing values?

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...