views:

169

answers:

6

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.

+15  A: 

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

If you need it, you must declare it.

sleske
And when you declare it, it should be a ListIterator if you're planning on removing items from the list.
Jack Cox
+1  A: 

Use a for loop instead.

Tyler
+4  A: 

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();
   }
}
Roman
I general prefer the `for` idiom rather than the `while` idiom because it keeps the scope of the iterator smaller.
dty
@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.
Roman
A: 

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**

Aardvocate Akintayo Olusegun
-1 Your wrong feel has a wrong feel to it.
Erick Robertson
+1  A: 

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;}
    });
Peter DeWeese
A: 

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.

Shawn