8

I very much like the for-each-loop construction (for(T e : iterable)) in Java which works on any Iterable<T> because it makes in many cases very easy to read and to write code.

I wonder though if there is any way that I can access the underlying iterator from such a loop. This can be mandatory if I want to use the remove() from the iterator.

6 Answers 6

17

No, the whole point of the for-each-loop is to abstract away the underlying iterator.

If you need it, you must declare it.

Sign up to request clarification or add additional context in comments.

1 Comment

And when you declare it, it should be a ListIterator if you're planning on removing items from the list.
4

No, you cannot remove objects in a for each loop.

Use this instead:

Iterator<Type> it = collection.iterator();

while (it.hasNext()) {
   if (it.next().shouldBeRemoved()) {
       it.remove();
   }
}

2 Comments

I general prefer the for idiom rather than the while idiom because it keeps the scope of the iterator smaller.
@dty: there is a valid point in your desire to keep all variables scope as narrow as possible. But as for me, code readability is on the first place. My version could be read almost as normal sentence: 'while iterator has next element do the following: ...', and yours seems very cumbersome. So, if we want to keep benefits from both approaches, it's worth to extract mine code to a separate method. That's the best we can do with this problem, IMHO.
1

Use a for loop instead.

Comments

1

If the collection is reasonably small, you can alternatively use a copy of the collection to iterate if you want to be able to remove elements so you won't have to act as if you have two collections.

for(T e : collection.clone())
    if(e.shouldBeRemoved())
        collection.remove();

Even better, Apache CollectionUtils (and there is probably a Google alternative and a generics alternative) provides filter(java.util.Collection collection, Predicate predicate). This example returns the whole list. You can store a predicate for reuse.

CollectionUtils.filter(collection, new Predicate(){
        boolean evaluate(Object object){return true;}
    });

Comments

1

You are correct, using an Iterator supports the ability to remove an object from a source collection safely, by calling remove() on the Iterator itself. The point here is to avoid a ConcurrentModifiedException which implies that a collection was modified while an Iterator was open against it. Some collections will let you get away with removing or adding elements to a Collection while iterating across it, but calling remove() on the Iterator is a safer practice.

But Iterator supports a derived and more powerful cousin ListIterator, only available from Lists, supports both adding and removing from a List during iteration, as well as bidirectional scrolling through Lists.

Comments

0

modifying data has a wrong feel to it, Just create a new Iterable(or collection) and add the items you want to keep to it, the other times are lost in the for loop ((kinda**

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.