简体   繁体   中英

ConcurrentModificationException while iterating through Arraylist (not removing)

I currently have a problem with iterating through an ArrayList. I've read several posts here, but nothing seem to have resolved my problem. Here is my code:

//restaurants contains a list of all restaurants and i want to filter them
List<Restaurant> newList = new ArrayList<Restaurant>();
List<Restaurant> allRestaurants = new ArrayList<Restaurant>(restaurants);
if (query != null && query.length() > 0 && !query.equals("*")) {
            synchronized (allRestaurants) {
                for (Iterator<Restaurant> it = allRestaurants.iterator(); it
                        .hasNext();) {
                    Restaurant restaurant = it.next();
                    if (restaurant.getCity().contains(query)) {
                        synchronized (newList) {
                            newList.add(restaurant);
                        }
                    } else {
                        newList = allRestaurants;
                    }
                }
            }

This is code was modified by me with several ideas i've read here (synchronized, using iterator instead of for-each-loop). I even have synchronized the whole method and still get an exception.

The exception is happening in following line:

Restaurant restaurant = it.next();

which I don't understand. I am not manipulating the list in this line. Why is this happening and how can i fix it?

else{
    newList = allRestaurants;
}

That is almost certainly your issue.

Assigning newList to allRestaurants then adding to newList is causing your comodification.

That is after newList = allRestaurants any add to newList will update the mod count in allRestaurants and thus your error.

In the else branch

else {
   newList = allRestaurants;
}

You set newList to be allRestaurants . The next modification newList.add(restaurant); changes the allRestaurants-list.

The exception is thrown when it.next() is called, because then the iterator checks if its source was changed.

The failure starts with:

newList = allRestaurants;

which points both references to the same list (ie the one you are iterating over). You then do the following:

newList.add(restaurant);

modifying the list. From the javadoc of ConcurrentModificationException :

Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.

Your problem is in the else clause.

         newList = allRestaurants;

That's why you get exceptions

You can't change the ArrayList that is used for iteration inside a loop; that is what ConcurrentModificationException says ( http://docs.oracle.com/javase/1.4.2/docs/api/java/util/ConcurrentModificationException.html ) and newList = allRestaurants; plus newList.add(restaurant); does potentially change the list allRestaurants .

So what you could do is

  1. create another list
  2. put items to modify in that list
  3. add/remove the new list ( addAll or removeAll ) to your old one after the loop

Check out http://www.javacodegeeks.com/2011/05/avoid-concurrentmodificationexception.html for more.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM