7

I get an error on the following line. I'm doing the process of adding to the jsonarray. Please help me.

jsonArr=new JSONArray();
if(req.getSession().getAttribute("userses")!=null){
    String name=(req.getParameter("name")==null?"":to_EnglishName(req.getParameter("name").toUpperCase()));
    if(!name.equals("")){
        for(Book c:GlobalObjects.bookList){
            if(c.getBookName().startsWith(name)){
                    jsonObjec=new JSONObject();
                    jsonObjec.put("label",c.getBookName());
                    jsonObjec.put("value", c.getId());
                    jsonArr.add(jsonObjec);//java.util.ConcurrentModificationException
            }
        }
    }
}
jsonArr.write(res.getWriter());
aliplane
  • 875
  • 3
  • 8
  • 9

7 Answers7

18

This is an error I often met while reprogramming. the reason or detail of this exception are pretty clear. it is unallowed to modify the collection(you are adding a new element) while it is being iterated. At least the syntax for DO NOT support do that.

To fix your problem, there have two way I think it is simple.

1). rather than using for statement to loop over, the better way is to use iterator to avoid ConcurrentModificationException.

    Iterator<Book> iterator = bookList.iterator();
    while(iterator.hasNext()){
      Book c = iterator.next();
      if(c.getBookName().startsWith(name)){
                jsonObjec=new JSONObject();
                jsonObjec.put("label",c.getBookName());
                jsonObjec.put("value", c.getId());
                jsonArr.add(jsonObjec);
        }
    }

2). while looping it, don't add it.

     List list = new ArrayList<>();
     for(Book c:GlobalObjects.bookList){
        if(c.getBookName().startsWith(name)){
                jsonObjec=new JSONObject();
                jsonObjec.put("label",c.getBookName());
                jsonObjec.put("value", c.getId());
                list.add(jsonObjec);//java.util.ConcurrentModificationException
        }
     }
     jsonArr.addAll(list);
C.c
  • 1,905
  • 6
  • 30
  • 47
3

To fix this problem, make sure that If your collection is not thread safe then it must not get modified with another thread when some other thread is iterating over this collection.

There are two possible ways to fix this problem -

1) One solution is to synchronize all access to the collection

2) Use Thread safe collection like CopyOnWriteArrayList

From Java Doc -

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

For example, it is not generally permssible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Pramod Kumar
  • 7,914
  • 5
  • 28
  • 37
2

You get ConcurrentModificationException when you are iterating over a collection and you modify the same collection within the loop. The given code snippet does not show that, so there is something else above or below modifying the collection. Try declaring the jsonArr right at the place where you instantiate it.

One possible reason could be the jsonArr instance Object is class level and is accessed by multiple threads. Declare the jsonArr object where it is instantiated.

Edit: Make jsonArr a local variable.

devang
  • 5,376
  • 7
  • 34
  • 49
  • accessing code from inside the Servlet.I use the autocomplete for. – aliplane Jul 10 '12 at 07:49
  • When coding in multi-threaded environment, like web applications, keep scope of your variables as local as possible. You will not face such issues. – devang Jul 10 '12 at 14:10
1

Also one more way is there, ie insted of passing actual list , we can pass clone of list for iteration.

listForIteration = list.clone();

//Do operation..

Adarsh Gowda
  • 196
  • 2
  • 13
0

Are you accessing jsonArr from another thread? i.e. Iterating over jsonArr when you are modifying it at the same time.

ConcurrentModificationException is thrown when you modify a collection at the same time while iterating it.

18bytes
  • 5,951
  • 7
  • 42
  • 69
  • as devsundar says, this shouldn't cause a CME unless jsonArr is multithread accessed. Is it? – MJB Jul 10 '12 at 06:27
  • From the code i see that jsonArr is only modified, and its not accessed at the same time. If aliplane is getting CME at the line mentioned, then jsonArr should be modified from another location or thread. – 18bytes Jul 10 '12 at 06:29
0

Or use a ListIterator which allows iterating and modifying the same list

http://docs.oracle.com/javase/6/docs/api/java/util/ListIterator.html

Martin
  • 1
  • 1
    Link-only answers are discouraged, SO answers should be the end-point of a search for a solution (vs. yet another stopover of references, which tend to get stale over time). Please consider adding a stand-alone synopsis here, keeping the link as a reference – Alex Sep 25 '13 at 12:14
0

just use java.util.concurrent.CopyOnWriteArrayList

List<String> empList = new CopyOnWriteArrayList<>();
empList.add("Mojtaba");
empList.add("Mojtabye");
empList.add("Yeganeh");

for (String item : empList) {
    System.out.println(item);
    empList.add("test");
}
Mojtaba Yeganeh
  • 2,788
  • 1
  • 30
  • 49