Reputation: 3890
How does Iterator
throw ConcurrentModificationException
when we are adding some object after current node or removing some object after current node. Does Iterator
maintain a copy or reference to the underlying collection?
Upvotes: 5
Views: 5550
Reputation: 3178
For removing you can use iterator.remove(), as follows:
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Object object = iterator.next();
/* ... */
if (condition) {
iterator.remove();
}
For adding you can replace simple Iterator for ListIterator, as follows
ListIterator<Object> iterator = list.listIterator();
iterator.add(new Object());
Upvotes: 1
Reputation: 3158
That ConcurrentModificationException is probably your friend and you ought to learn to live with it. However, just for completeness:
There are non-Oracle collections out there that don't throw ConcurrentModificationException. They're faster (because they don't spend time checking) and, obviously, more flexible, but they require greater care when using.
Oracle has four (at last count) "Concurrent" classes that don't throw it either in java.util.concurrent (ConcurrentHashMap, ConcurrentLinkedQueue, ConcurrentSkipListMap, and ConcurrentSkipListSet). They're marginally slower than their non-concurrent equivalents, but they're thread-safe and they dont block. They won't scramble your data no matter what you do, but they won't stop you from scrambling it.
Upvotes: 1
Reputation: 500367
By contract, you are not allowed to modify the collection while iterating over it (except by using Iterator.remove()
et al).
Instead of randomly failing when you do this, the collection is nice enough to keep track of how many times it's been modified, and throw ConcurrentModificationException
when it detects concurrent modification.
Upvotes: 2
Reputation: 198103
The iterator maintains a reference to the underlying collection. If you add or remove an element, the iterator might be left at an impossible index, or the collection might change "out from underneath" the iterator.
Therefore, instead of letting the iterator get corrupted without letting you know, most collections do the courtesy of throwing a ConcurrentModificationException when you try to modify the collection while iterating, so you don't wind up with unpredictably corrupted iterators.
Upvotes: 5
Reputation: 382150
Of course an iterator has a link to the underlying collection, this avoids the copy. If you look for example at the source code of ArrayList iterator (ListItr), you'll see it mostly has a link to the list and a cursor.
So, don't share an iterator between threads and don't modify a collection on which you're iterating.
Upvotes: 0