When the enhanced for loop (foreach loop) was added to Java, it was made to work with a target of either an array or Iterable
.
for ( T item : /*T[] or Iterable<? extends T>*/ ) {
//use item
}
That works great for Collection classes that only implement one type of iteration, and thus have a single iterator()
method.
But I find myself incredibly frustrated the odd time I want to use a non-standard iterator from a Collection class. For example, I was recently trying to help somebody use a Deque
as a LIFO/stack but then print the elements in FIFO order. I was forced to do this:
for (Iterator<T> it = myDeque.descendingIterator(); it.hasNext(); ) {
T item = it.next();
//use item
}
I lose the advantages of the for-each loop. It's not just about keystrokes. I don't like exposing the iterator if I don't have to, since it's easy to make the mistake of calling it.next()
twice, etc.
Now ideally I think the for-each loop should have accepted an Iterator
as well. But it doesn't. So is there an idiomatic way of using the for-each loop in these circumstances? I'd also love to hear suggestions that use common collections libraries like Guava.
The best I can come up with in absense of a helper method/class is:
for ( T item : new Iterable<T>() { public Iterator<T> iterator() { return myDeque.descendingIterator(); } } ) {
//use item
}
Which isn't worth using.
I'd love to see Guava have something like Iterables.wrap
to make this idiomatic, but didn't find anything like that. Obviously I could roll my own Iterator wrapper via a class or helper method. Any other ideas?
Edit: As a side-note, can anybody give a valid reason for why the enhanced for-loop shouldn't have been able to just accept an Iterator
? It would probably go a long way to making me live with the current design.
ImmutableList.copyOf(Iterator)
to safely convert an Iterator into an Iterable. See the above link for more on why. – Piddle