I think by now most of the developers agree on the value of the concept of iterators. Instead of looking “inside” collections in order to traverse them we can use a separate concept of iterators and do what we need without knowing anything about the way the collections are implemented.

The iterator is basically a simple concept and is usually expressed as an interface that various implementations conform to. In early Java versions, the iterator was called Enumeration and had two methods:

boolean hasMoreElements(); // returns true if there are more elements to traverse
Object nextElement(); // returns element that iterator is “at” and moves to the next

This is very similar to how early .NET versions designed iterators. In .NET the iterator is called IEnumerator and has one property (syntactic sugar representing a “get” style Java method) and two methods:

object Current; // get current element iterator is “at”
bool MoveNext(); // move to the next element and return false if no more elements
void Reset(); // go back to the beginning of sequence

As you can see, the difference is negligible. The only thing the .NET added was the capability to go “back” to the beginning without having to create a new iterator.

Later Java versions introduced Iterator, another interface to model iterators and this is where things start to stink. Here’s how Iterator looks like:

boolean hasNext(); // like Enumeration.hasMoreElements
Object next(); // like Enumeration.nextElement
void remove(); // removes element iterator is “at” (?!?)

The last method is problematic because it destroys the whole concept of “iterators are the means to traverse the collections”. If you look at all the other libraries that support iterator concepts, you’ll see that remove is usually a method on a collections that accepts an iterator. There is no need for remove method on an iterator.

But wait, there’s more. How do you iterate a List in Java? By using ListIterator (which at least derives from Iterator so not all is lost). ListIterator adds six more methods – things like previous (to move back in the sequence), add (add an element to the end of the sequence) etc. This is wrong – it fragments the concept of iterator (you never know which interface to use) and adds unnecessary methods to the iterator interface.

You could argue that adding something like previous is a good thing - after all, how would one go at iterating backwards if there was not a method like previous? And you would be right – if indeed the bi-directional iterator was deemed necessary, it should have been added to the base interface, not just to the ListIterator.

Contrast this to the latest .NET iterator related concepts. The iterator is still the same (with slight improvement with the introduction of generics) while a few new keywords (yield return, yield break) were added to simplify the creation of iterators (I wrote about it recently). The new keywords are supported by a compiler generating a small state machine so no extra work for the developer nor the need to change anything regardless the iterator concept. Don’t forget – since the very beginning, you could do the very frequent foreach style iteration in the .NET for the same reason – the compiler would generate the code using IEnumerator for you.

The rule of keeping it simple apparently did not ring as true with Java folks as it did with Microsoft. Having a single iterator concept while still improving the language(s) and iteration is possible as the .NET clearly shows. Why Java chose the way it chose is beyond me.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
0 Comments