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 : /*
public class DescendingIterableDequeAdapter<T> implements Iterable<T> {
private Deque<T> original;
public DescendingIterableDequeAdapter(Deque<T> original) {
this.original = original;
}
public Iterator<T> iterator() {
return original.descendingIterator();
}
}
And then
for (T item : new DescendingIterableDequeAdapter(deque)) {
}
So, for each such case, you'd need a special adapter. I don't think it is theoretically possible to do what you want, because the facility has to know what iterator-returning methods exist, so that it can call them.
As for your additional question - I believe because the for-each loop was actually meant to make things shorter for general-purpose scenarios. And calling an additional method makes the syntax more verbose. It could've supported both Iterable
and Iterator
, but what if the object passed implemented both? (would be odd, but still possible).
I suggest to create a helper class with factory methods that you can use like this:
import static Iter.*;
for( Element i : iter(elements) ) {
}
for( Element i : iter(o, Element.class) ) {
}
As a next step, the return type of iter()
could be a fluent interface so you can do:
for( Element i : iter(elements).reverse() ) {
}
or maybe
for( Element i : reverse(elements) ) {
}
You should also have a look at op4j which solves many of these problems with a very nice API.
Guava users can do ImmutableList.copyOf(Iterator)
to safely convert an Iterator into an Iterable. Despite the seeming simplicity of looping over an Iterator, there are concerns that foreach hides, and the safest option is to create a stable data structure like a list.
This is also discussed in the Idea Graveyard:
The biggest concern is that
Iterable
is generally assumed to be able to produce multiple independent iterators. The doc doesn't say this, but theCollection
doc doesn't say this, either, and yet we assume it of its iterators. We have had breakages in Google when this assumption was violated.The simplest workaround is
ImmutableList.copyOf(Iterator)
, which is pretty fast, safe, and provides many other advantages besides.