Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Iterator's remove method actually remove an object

We all know that the safest "and probably only safe" way of removing an object from a collection while iterating it, is by first retrieving the Iterator, perform a loop and remove when needed;

Iterator iter=Collection.iterator(); while(iter.hasNext()){     Object o=iter.next()     if(o.equals(what i'm looking for)){         iter.remove();     } } 

What I would like to understand, and unfortunately haven't found a deep technical explanation about, is how this removal is performed,
If:

for(Object o:myCollection().getObjects()){     if(o.equals(what i'm looking for)){         myCollection.remove(o);     } } 

Will throw a ConcurrentModificationException, what does "in technical terms" Iterator.remove() do? Does it removes the object, breaks the loop and restart the loop?

I see in the official documentation:

"Removes the current element. Throws IllegalStateException if an attempt is made to call remove() that is not preceded by a call to next( )."

The part "removes the current element", makes me think of the exact same situation happening in a "regular" loop => (perform equality test and remove if needed), but why is the Iterator loop ConcurrentModification-safe?

like image 620
JBoy Avatar asked Apr 13 '13 21:04

JBoy


People also ask

How does remove work in iterator?

An element can be removed from a Collection using the Iterator method remove(). This method removes the current element in the Collection. If the remove() method is not preceded by the next() method, then the exception IllegalStateException is thrown.

How does the remove method work in Java?

The remove method returns true if an object passed as a parameter is removed from the list. Otherwise, it returns false. The remove method returns the removed element if an index is passed. It throws IndexOutOfBoundsException if the specified index is not in range.

What is difference between remove () method of collection and remove () method of iterator?

As per Sun , "Iterator. remove is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress."


1 Answers

The reason why you cannot modify a list while iterating over it is because the iterator has to know what to return for hasNext() and next().

How this is done is implementation specific, but you could have a look at the source code of ArrayList/AbstractList/LinkedList etc.

Also note that in some situations you can use some code like this as an alternative:

List<Foo> copyList = new ArrayList<>(origList); for (Foo foo : copyList){   if (condition){     origList.remove(foo);   } } 

But this code will probably run slightly slower because the collection has to be copied (shallow copy only) and the element to remove has to be searched.

Also note that if you're using the iterator directly it's recommended to use a for loop instead of while loop as this limits the scope of the variable:

for (Iterator<Foo> iterator = myCollection.iterator(); iterator.hasNext();){ ... } 
like image 200
Puce Avatar answered Sep 18 '22 08:09

Puce