Java - Exception in thread “main” java.util.ConcurrentModificationException

≯℡__Kan透↙ 提交于 2020-01-30 03:25:09

问题


Is there any way I can modify the HashMap values of a particular key while iterating over it?

A sample program is given below:

public static void main(String[] args) {
    HashMap<Integer,ArrayList<String>> hm = new HashMap<Integer, ArrayList<String>>();      
    ArrayList<String> ar = new ArrayList<String>(); 
    for(int i=0;i<50;i++){              
        ar.add(Integer.toString(i));            
    }

    hm.put(1, ar);      

    for(String s:hm.get(1)){
        hm.get(1).add("hello");
    }

}

Error Thrown:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    at Excp.main(Excp.java:17)

回答1:


This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.

Below peice of code is causing the problem.

for(String s:hm.get(1)){
        hm.get(1).add("hello");
    }

You are iterating and modifying the same. Avoid this by creating new ArrayList

  ArrayList<String> ar1 = new ArrayList<String>();

for (String s : hm.get(1)) {
            ar1.add("hello");
        }

have a read here




回答2:


When we are trying to modify collection object while iterating then we get this exception. Check following code:

for(String str : stringList){ 
   stringList.add("Test");
}

So in above we get runtime exception.

Solution

Use iterator over For-Each loop, like:

static void filter(Collection<?> c) {
    for (Iterator<?> it = c.iterator(); it.hasNext(); )
       if (!anyCondition(it.next()))
          it.remove();
}

So basic difference between For-Each and iterator is, we can modify collection while iterating using only iterator.




回答3:


The problem in the code your presented isn't modifying the HashMap, it's modifying the ArrayList while iterating it. You can avoid this exception if you use ar's ListIterator instead of using an enhanced for loop:

for (ListIterator<String> i = ar.listIterator(); i.hasNext(); i.next()) {
    i.add("hello");
} 



回答4:


If try to modify while iterating your list you will get this Exception.

for(String s:hm.get(1)){ // iterate 
    hm.get(1).add("hello");//modify
}

Both operation affect to hm

You don't need to iterate here. Just use

hm.get(1).add("hello");



回答5:


If you want to add to the original ArrayList, then iterate through it on your own:

final ArrayList<String> arr = hm.get(1);
final int size = arr.size();

// this will add size number of "hello" strings to ArrayList arr
for(int i = 0; i < size; ++i){
    // you don't appear to ever use this value
    final String s = arr.get(i);

    // do something to arr
    arr.add("hello");
}



回答6:


Although not related to the question, but just adding

ConcurrentModificationException can also occur if you get the iterator over a collection first and then add some more elements over it and then iterating over the collection will throw this exception.

For example :

package got;

import java.util.*;

public class GotCharacters {


    public static void main(String... args){

        Person p1 = new Person("TL", 40, "Tyrion Lannister");
        Person p2 = new Person("JM", 50, "Jorah Mormont");
        Person p3 = new Person("AS", 20, "Arya Stark");

        //Defining the collection and adding some elements
        ArrayList<Person> al;
        al = new ArrayList<Person>();
        al.add(p1);
        al.add(p2);
        al.add(p3);

        //Getting the iterator
        Iterator<Person> itr = al.iterator();

        Royalty r1 = new Student("DT", 25, "Daenerys Targaryen", "DragonMother", "Targaryen");
        Royalty r2 = new Student("JS", 28, "Jon Snow", "Lord Commander", "Targaryen");
        Collection<Royalty> c = new ArrayList<Royalty>();
        c.add(s1);
        c.add(s2);

        //Adding more elements after getting the iterator
        al.addAll(c);

        while(itr.hasNext()){
            System.out.print(itr.next());
        }
    }
}

Outcome :

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
    at java.util.ArrayList$Itr.next(ArrayList.java:851)
    at myArrayList.ArrayList1.main(ArrayList1.java:34)



回答7:


Concurrent Modification in programming means to modify an object concurrently when another task is already running over it. Fail Fast And Fail Safe Iterators in Java Iterators in java are used to iterate over the Collection objects. Fail-Fast iterators immediately throw ConcurrentModificationException if there is structural modification of the collection. Fail-Safe iterators don’t throw any exceptions if a collection is structurally modified while iterating over it. This is because, they operate on the clone of the collection, not on the original collection and that’s why they are called fail-safe iterators. Please use ConcurrentHashMap if you want to modify in between.



来源:https://stackoverflow.com/questions/26418325/java-exception-in-thread-main-java-util-concurrentmodificationexception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!