Panasonic Youth rob sanheim writes about software, business, ruby, music, stuff and things



Posted
22 August 2005 @ 11am

Tagged
Java, Patterns

Discuss

preferred Iterator usage - use “for”, not “while”

Note: this tip not quite as applicable with Java 5.

One of my pet peeves is coming up this loop construct for iteration - don't use this:

JAVA:
  1. Iterator iter = widgets.iterator();
  2. while(iter.hasNext()) {
  3.     foo(widgets.next());
  4. }

Instead, use the "for loop idiom". It minimizes the scope of the iterator and is a safer, shorter, and is clearer:

JAVA:
  1. for(Iterator iter = widgets.iterator(); iter.hasNext();) {
  2.     foo(widgets.next());
  3. }

Good ole' Effective Java has a nice example of the kind of copy-and-paste bugs that can happen with the first idiom:

JAVA:
  1. Iterator i = c.iterator();
  2. while(i.hasNext()) {
  3.     foo(i.next());
  4. }
  5. // other code
  6. Iterator i2 = c2.iterator();
  7. while(i.hasNext()) {
  8.     foo(i2.hasNext());
  9. }

Do you see the bug? Its easy to see here, of course, but could be tough to find in practice as it runs fine but just functions incorrectly. It would be a compile time error if you went with the for construct. Its always best to keep your variable scope as small as possible, and the for loop also makes refactoring cleaner if you want to extract the loop block out.


11 Comments

Posted by
PJ Hyett
22 August 2005 @ 1pm

I’m not so sure the for loop is clearer. You can read the while loop out loud and it does exactly what it sounds like it’s supposed to do. That having been said, I prefer the for loop because of the tighter syntax.


Posted by
aaa
22 August 2005 @ 4pm

yes as you said i am enjoyin Java 5 for (:).. very few times i need iterators now. Also a hint; in idea if you write “itco” and press “tab” it creates a for iterator for the nearest collection immediately. you also edi the field names if you like with consequent Tab hits.. very nice, no hassle.


Posted by
Tom Copeland
22 August 2005 @ 5pm

Right on! Of course, sometimes you see the opposite thing, something like:

void bar(Iterator i) {
for (;i..hasNext();) {
// do something
}
}

where the for loop can be collapsed into a while loop. PMD has a rule to catch that case:

http://pmd.sourceforge.net/rules/basic.html#ForLoopShouldBeWhileLoop


Posted by
Rob
22 August 2005 @ 7pm

PJ: I’m not sure if either really “reads” better then the other- I read the while loop as “while widgets has elements, do foo”, and the for loop as “for every widget, do foo” - so they are pretty close. The Java 5 syntax seems best for readability, as it translates do “for each foo do x”.


Posted by
Rob
22 August 2005 @ 7pm

Tom: True - thats a case where I wish Java had support for internal iterators in some way, either with closures or C# style delegates. Oh well…


Posted by
R.J. Lorimer
22 August 2005 @ 9pm

I have a tendency to agree with these types of statements; as I am a big fan of minimized lexical scope. That being said, I am leery of spending too much time worrying about it. In all honesty, I can’t recall a time where I have seen a bug in code actually caused by an iterator that had scope outside of the loop it was introduced in. Most times loops of this sort are isolated to their own method (or fairly closesly in anycase). While I do agree that the scope issue is solved with the for loop, the readability does decrease in the code, and with so many more difficult problems to solve, as long as the developer base for a particular application is competent, this is typically not something I want my team worrying about in too much detail.


Posted by
Simon Harris
22 August 2005 @ 9pm

I find for-loops much easier to understand but I’ve found that many junior developers and non-technical people actually find the while variant easier.

Having worked with JavaScript for a teeny bit now, I must admit that closures would be nice in _most_ cases.

Again though, I’d have to stress that although I find the .each with a closure much easier to read but I’ve run it by some non-technical people and junior developers who find it harder to understand.

I guess like many things, it’s what you’re used to?


Posted by
Rob
23 August 2005 @ 2am

RJ: I think the readability advantage for “while” is arguable, though i would agree that decent devs should be able to read either way. All the more reason to simply standardize on the for loop and forget about it.

Simon: You mean junior devs find the “for(String line : textfile)” construct difficult? Maybe its just due to the unfamiliarity of java 5?


Posted by
Simon Harris
23 August 2005 @ 9am

Rob: Actually I haven’t asked them what they think of for(:) only the traditional for(;;). I assume–though I’m sure I’d be wrong–that the newer version is _more_ readable. But again, a you suggest, I’m pretty sure it mainly comes down to what you are used to.


Posted by
Scott Vachalek
23 August 2005 @ 2pm

In most languages other than C derivatives, the “for” statement is provided as a straightforward counting structure. In comparison the C version is a bizarre bit of syntax that doesn’t really do anything for you other than let you put the first and last statement of a “while” loop inside the loop declaration, with nothing but position and an overloaded semicolon operator to separate the mess. Given that, I understand those who don’t find the for(;;) syntax to be particularly enlightening or appealing. It’s not surprising that Sun finally decided it needed a better way to iterate.

The scoping thing vs. “while” is nice but really, if your methods have multiple iterations that aren’t nested you are probably looking at two different operations. You should clarify the purpose of the two different iterations, either by refactoring into separate methods with enlightening names or by picking a better name than “i” for the iterator.


Posted by
Greg
14 February 2008 @ 11am

If you are really in a position to start enforcing code standards you may want to start with banning variables that are not descriptive in the first place. Especially when you have multiple loops near each other. Its awful nice to be able to tell by the variable names what the loop is for and that would go a long way in preventing i1 and i2 from being swapped. So before I started trying to standardize on for or while loops I would attempt to get decent variable naming conventions in place.


Leave a Comment

Comparing Ruby Symbols to Java String interning Prototype JavaScript library documentation