Reputation: 1271
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?
Upvotes: 3
Views: 2273
Reputation: 13967
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
addAll
or removeAll
) to your old one after the loopCheck out http://www.javacodegeeks.com/2011/05/avoid-concurrentmodificationexception.html for more.
Upvotes: 0
Reputation: 9162
Your problem is in the else clause.
newList = allRestaurants;
That's why you get exceptions
Upvotes: 0
Reputation: 25084
The failure starts with:
newList = allRestaurants;
which points both references to the same list (i.e. 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.
Upvotes: 0
Reputation: 15145
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.
Upvotes: 0
Reputation: 40276
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.
Upvotes: 4