File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Beginning Java and the fly likes Concurrent Modification Exception Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Concurrent Modification Exception " Watch "Concurrent Modification Exception " New topic
Author

Concurrent Modification Exception

Manoj Raghuwanshi
Ranch Hand

Joined: Jun 20, 2004
Posts: 75
I want to iterate a list and at the same time modify it. List contains object of Strings.
But it is throwing Concurrent Modification Exception . Please tell me to solve this problem.
Edwin Dalorzo
Ranch Hand

Joined: Dec 31, 2004
Posts: 961
The javadoc API explains the causes of the problem

...it is not generally permissible 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 general purpose 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.


You could use another ways to iterate and modify your list instead of iterator. For instance the List interface offer the get(index) and the set(index,value) methods.

Another thing you must keep in mind is the importance of synchronizing access to your collection, at least using Collections.synchronizedList(List list).

[ October 06, 2006: Message edited by: Edwin Dalorzo ]
[ October 06, 2006: Message edited by: Edwin Dalorzo ]
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

Manoj --

Most of the time if someone wants to iterate and modify a list at the same time, it's to inspect all the elements and remove some of them. Note that the Iterator interface has a remove() method which removes the current element (the last one returned by "next()".) Not all Iterators implement remove(), but many in the Collections API do. If you use Iterator.remove() to remove your elements, there will be no ConcurrentModificationException.


[Jess in Action][AskingGoodQuestions]
Manoj Raghuwanshi
Ranch Hand

Joined: Jun 20, 2004
Posts: 75
Thanks for help.
What I'm thinking is - while iterating over the list, inspect the objects and copy those objects in to another list. Then remove this list from the original by using List.removeAll(Collection c).
Peter Chase
Ranch Hand

Joined: Oct 30, 2001
Posts: 1970
Originally posted by Manoj Raghuwanshi:
Thanks for help.
What I'm thinking is - while iterating over the list, inspect the objects and copy those objects in to another list. Then remove this list from the original by using List.removeAll(Collection c).


You could do that, but why not use the Iterator.remove() method, like the wise EF-H says?


Betty Rubble? Well, I would go with Betty... but I'd be thinking of Wilma.
Edwin Dalorzo
Ranch Hand

Joined: Dec 31, 2004
Posts: 961
Well, the exception just happens if the list is modified before you finish to use the iterator. For instance the following code will produce ConcurrentModificationException.



But this code would not:



Ernest's suggestion is that you use a ListIterator and use the remove method. Like this

Manoj Raghuwanshi
Ranch Hand

Joined: Jun 20, 2004
Posts: 75
Sorry please ignore my previous comment of sorting out the objects in to another list and then use List.removeAll() because that dont work. Let me explain my requirement-
My program :-

List list =getList(); // A method that will return a list of Integer //objects [1,2,3,4]

for(int i=0;i<list.size();i++){
Object temp=list.get(i);
If(temp instanceof Integer){
Integer id=(Integer) temp;
// Business logic to get parent-attachment document numbers for this id
//if those ids present in this list remove at this point from the underlying //list , here I cant do because in that case I cant use for loop to iterate //I must use iterator and that will throw concurrent modification //exception. So mark these documents as String.
List paList=getParentAttachment(id);
for(int j=0;j<paList.size();j++){
Integer doc=(Integer) paList.get(j);
if(list.contains(doc)){
int position=list.indexOf(doc);
list.remove(position);
list.add(position,"String");
}
}
}
}
// Remove all string objects from list
Iterator it=list.iterator();
while(it.hasNext()){
Object obj=it.next();
if(obj instanceof String)
it.remove();
}


I know this is crud but i dont see any other solution, may be a design pattern?
Edwin Dalorzo
Ranch Hand

Joined: Dec 31, 2004
Posts: 961
Well, at first sight, it appears that your code will not produce ConcurrentModificationException.

I may be work, but your second inner loop seems to look for integers in the list and then replace them with a String object, and at the end, you remove all Strings from the list.

I cannot say that is bad, but why do you add a String to the list if you prented to delete it right after inserted it?
Manoj Raghuwanshi
Ranch Hand

Joined: Jun 20, 2004
Posts: 75
Because in for loop
for(int i=0;i<list.size();i++) , list.size() will return the initial size of the list and inside this for loop if I remove any object using list.remove(index) , the list will throw ArrayIndexOutOfBound Exception.I am replacing the Integer objects at that position in the list with String object so List size remain the same throughout the iteration of the for loop.
Edwin Dalorzo
Ranch Hand

Joined: Dec 31, 2004
Posts: 961
What if instead of removing the object while iterating your list, you add your findings to another list, named itemsToBeRemoved, then at the end of the loop you simple remove your findings with list.removeAll(itemsToBeRemoved)?
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Concurrent Modification Exception