Friday, July 27, 2007

How to Properly Iterate a Collection in Java

There are multiple ways to iterate a collection in Java among many other things but that doesn't mean all are equally elegant or easy on the eyes. Just as some ways to skin a cat are messier than others (Not that I have ever skinned a cat or any other animal for that matter). Anyhoo I'm making this post in hopes of at least few developers starting on Java will see it before starting to write code in a commercial project.

I came across a code base of a project that was developed mostly by a bunch of junior developers and most of the code that iterates a collection was in the following format

List administrators = getAdministrators();

if (administrators.size() > 0) {
Iterator administratorsItr = administrators.iterator();
Administrator administrator = null;
while (administratorsItr.hasNext()) {
administrator = (Administrator) administratorsItr.next();
//rest of the code block removed
}
}
}

Just looking at that piece of code made my head spin :). The worst part was that this is the style most of the junior developers had adopted and could be seen all over the code base.

Just for the record I would have written it in the following way (actually would have let the IDE write it for me)

List administrators = getAdministrators();

for (Iterator iter = administrators.iterator(); iter.hasNext();) {
Administrator administrator = (Administrator) iter.next();
//rest of the code block removed
}

The above two code blocks achieve the same thing, the difference been, first is 9 lines long and the second is 4 lines. Most importantly you can figure out whats going on easily by looking at the second code block.

The worst part is IDEs like IntelliJ IDEA will write it for you. All you have to do is type itco and press ctrl + space keys just after the List administrators = ... line.

I don't know if there is something similar on Eclipse but you can import all these nifty IDEA Live Templates into Eclipse. Just head over to this page where you can find the xml file and instructions on how to import the file.

Don' forget to click the +1 button below if this post was helpful.

18 comments:

Anonymous said...

If you're used to IJ IDEA, then try iter instead of itco :

List<Administrator> administrators = getAdministrators();

for (Administrator administrator : administrators) {
// rest of the code here
}

Generics and foreach loop are more readable, and type secure ;)

MEWG said...

Yep generics makes things even more cleaner but sadly I have to stick to JDK 1.4. Large enterprises tend to be slow when it comes technology progress :)

Anonymous said...

I see. I suppose you know about it, but after all, you could check an eye on Retrotranslator, which allows writing 1.5 code, then (retro)translate it to 1.4 compatible one.

http://retrotranslator.sourceforge.net/

MEWG said...

Hmmm...the Retrotranslator sounds interesting. I will take a look. Thanks.

btw.. I didn't know about the iter shortcut

Anonymous said...

In Eclipse, the shortcut is "for" (without the quotes). Type for then ctrl-space and it generates the for loop for you.

Anonymous said...

List administrators = getAdministrators();
int size = administrators.size();

for (int i = 0; i < size; i++) {
Administrator administrator = (Administrator)iter.next(); //rest of the code block removed}

This is more readable to me (if I was forced to use 1.4). But what do I know, I'm a junior developer :)

Anonymous said...

...and as a junior developer I'm allowed to introduce bugs like forgetting to create the iterator :)

Danie Roux said...

In IDEA, you can press "Ctrl-j" to get a list of templates/shortcuts available to you in the current context.

Including the ones you define yourself.

Anonymous said...

This seems like the shortest and simplest way to skin this cat to me

for (Administrator administrator : getAdministrators()) {
// rest of the code here
}

I'm assuming of course that getAdminstrators a collection of Administrator, rather than say, just a List

Anonymous said...

wow, what an idiot! he used while ? we all know its @deprecated, just like break and continue.

Its just like using indexOf when you should use regex, what a noob.

im happy that your IDE thinks for you, so you wont make his mistakes.

im also happy that you find those bugs and fix them, i bet they would cause memory leaks or someother stuff.

Unknown said...

Administrator administrator = (Administrator) iter.next();

you can improve further by declaring the Administrator variable out side the loop
so that it will not create the reference for every iteration

Anonymous said...

>you can improve further by declaring
> the Administrator variable out side
> the loop so that it will not create
> the reference for every iteration

so it should look like this?
if (administrators.size() > 0) {
Iterator administratorsItr = administrators.iterator();
Administrator administrator = null;
for (; administratorsItr.hasNext();) {
administrator = (Administrator) administratorsItr.next();
//rest of the code block removed
}
}
}

Steven said...

I know it has been over a year since the last post but I just stumbled upon this and wanted to clear something up. It actually does not change performance (contrary to popular belief) whether you declare Administrator inside the loop or outside.

EXAMPLE 1 (declare outside loop):
Administrator admin;
for (...)
{
admin = ...
}

EXAMPLE 2 (declare inside loop):
for (....)
{
Administrator admin = ...
}

Both perform the same! Why? This is because the Java compiler is smart enough to do EXAMPLE 1 even if you were to code EXAMPLE 2. So keep that in mind next time you encounter this situation.

Javin @ Tibco EMS Tutorial said...

Nice article , just to add the functionality of Enumeration interface is duplicated by the Iterator interface.
Iterator has a remove() method while Enumeration doesn't. Enumeration acts as Read-only interface, because it has the methods only to traverse and fetch the objects, where as using Iterator we can manipulate the objects also like adding and removing the objects.

to read more see here difference between iterator and enumeration

Android app development said...

This is one of the good quality post.Your blog information is very specific.This is one of the useful post.

Wachgellen said...

Good, the only thing I would add is the type to the iterator so you don't have to typecast in the loop:


List administrators = getAdministrators();

for (Iterator iter = administrators.iterator(); iter.hasNext();) {
Administrator administrator = iter.next();
//rest of the code block removed
}

Wachgellen said...

Oops, it didn't post properly, I meant this:

List<Administrator> administrators = getAdministrators();


for (Iterator<Administrator> iter = administrators.iterator(); iter.hasNext();) {
Administrator administrator = iter.next();
//rest of the code block removed
}

web security said...

The type casting required for the object returned by iter.next() is troublesome in many situations. If we look at the internal implementation of Java iterators, we can see how next, remove methods work and write better code.