Lets say I have a list returned by an arbitrary method:
List<E> someList = someObject.getList();
someList
can be changed at any time by someObject
in another thread. I have no access to the implementation of someObject
, and someObject.getList()
does not return a synchronized or immutable list implementation.
I want to iterate through someList
. Unfortunately, since the list can be changed, iterating through it normally doesn't work:
// Sometimes throws ConcurrentModificationException
for(E element : someObject.getList()) {
doSomething(element);
// ...
}
So how can I iterate through a list (not thread safe) returned by an alien method?
The general rule of thumb is that you don't modify a collection/array/list while iterating over it. Use a secondary list to store the items you want to act upon and execute that logic in a loop after your initial loop.
ArrayList provides the remove() methods, like remove (int index) and remove (Object element), you cannot use them to remove items while iterating over ArrayList in Java because they will throw ConcurrentModificationException if called during iteration.
Iterating using Iterator/ListIterator allows to add/remove element and these modification (add/remove) is reflected in the original List.
Maybe the other thread uses a synchronization mechanism like synchronized(list) for modifying the list; in that case you could use synchronized on the same object and you'd be safe.
List<E> list=someobject.getList();
synchronized (list) {
for (E element : list) {
doSomething(element);
}
}
You can try synchronizing on the list or on someObject and hope it works.
Other than that, I don't see any clean solution. In the end, if the other code that modifies the list doesn't care about other users of the list, it's pretty impossible to iterate safely.
Unclean one: try to copy the array in a loop until the ConcurrentModificationException is not thrown anymore.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With