Did the Java designers just not care?

Why does the Java foreach construction get compiled to an iterator loop and not just to a for(int i = 0;i < list.size(); i++) {}.

It seems to me the iterator implmentation is a classically lazy heap spammer. I just remembered to get rid of the foreach loops from my AABB code, but why do I need to do this? If the old Java 1 index increment loop is technically better and the end user syntax is the same either way, why does Java go the iterator() route?

So that you can foreach on any Iterable. (also arrays, but that’s a special case)

But for most cases I can do the index incrementor style… they didn’t need to apply the worst case scenario to ALL iterations.

My experience with the Hotspot compiler for about a year or so, is that the Iterable is completely removed. There is no object on the heap, it’s turned into local variables (native stack) and/or held completely in registers. They will show up in some profilers as objects on the heap, but that’s because these profilers inject bytecode that prevents the stack allocation optimisation. If you loop through nested loops of loops of loops backed by iterables, you’ll see no garbage is created. I think it’s safe to say that Iterables from the Collections API, in foreach-loops, are now almost guaranteed to be entirely optimized away.

Predictable stack allocation of arbitrary types is on the horizon. Value types are approaching the same problem from another angle, but the support will greatly enhance stack allocation optimisations.

Yadda. Yadda.

That sounds nice. How close is this to our daily lives? And at what Java version is the Iterable guaranteed to be gone? 8?

i dont trust it and rather loop it backwards. [icode]for( int i = list.size() ; i-- != 0 ; ) list.elements[i].; [/icode]

for native arrays i always use iterable, but i dont see how this would work with any custom collection. would be interesting to know how hotspot detects the default java collections. ???

It doesn’t. It just uses escape analysis to realize that the Iterator it creates can’t leak (it’s probably the most trivial case in the world since it’s even hidden from the user). Then it can just allocate the Iterator on the stack instead of on the heap by simply dumping the local variables of the Iterator on the stack, like Riven said.

BurntPizza already covered it, but let me expand: how would your “index foreach” work on data structures that have no concept of indexes? How would they work on a Set, for example? What about data structures where get(index) is much less efficient than an iterator, such as linked lists?

The Iterator approach allows us to “foreach” over custom classes just by implementing Iterable. With your approach, we’d have to implement a get(index), which doesn’t make sense for every (or even most?) data structures.

Besides that, nothing is forcing you to use the “enhanced for” shortcut. If you really need to iterate over your data structure by index, then you can still do that.

I assure you that the developers of Java have put more thought into this than any of us have. What exactly are you saying is the downside? What profiling have you done? What is the alternative?

To get a better understanding of the considerations that go into these kinds of decisions, I recommend Program Development in Java by Barbara Liskov, or really any of the books she’s written on API design, abstraction, and substitutability.

Absolutely right, however Hotspot still uses an Iterator on LinkedLists and similar data structures - and it makes sense. The optimization, btw, only applies to internal types because those optimizations are based on knowledge about the class. They are also completely Hotspot specific, IBM for example (with the J9 JVM) calls toArray and uses and index based loop.

The best thing actually (when on Java 8+) use internal iterations using Collection::forEach and it is up to the implementation of the collection to select the best iteration strategy. It also looks cleaner, easier to read and is way less boilerplate to write :slight_smile: