For, for each, while : What is the difference?

In Java you have several ways to iterate through a collection. This article is not about which one to choose but more about understanding which one does what. For those who are looking for an article telling them which one is the best : Stop searching and start coding! Pick the most elegant one depending on your situation.

Measuring Performance

I have developped a micro-benchmark to compare the different kind of iterations over a List. You can find the full source code on my github, but let’s have a look at the different method to iterate through a List.

//WHILE with iterator
                int sum = 0;
                Iterator<Integer> it = list.iterator();
                while (it.hasNext()) {
                    sum += it.next();
                }

// For with iterator
                sum = 0;
                for (Iterator<Integer> it = list.iterator(); it.hasNext();) {
                    sum += it.next();
                }

//for each syntax
                int sum = 0;
                for (Integer i : list) {
                    sum += i;
                }

//while increment
                int sum = 0;
                int i = 0;
                while (i < list.size()) {
                    sum += list.get(i);
                    i++;
                }
//for Increment
                int sum = 0;
                for (int i = 0; i < list.size(); i++) {
                    sum += list.get(i);

                }

Let’s measure the performance of by iterating over a list and doing the sum of a list of 1000 integers. On my machine it gives :

 benchLoops

Interpreting the benchmark results

The charts Y-Axis is in nano-seconds, so for the first chart, we can fairly say that all kind of iterations are similar. Even if we can notice that the two last scenarios are a bit faster.

The second chart shows that, for a LinkedList, the last two scenarios are way longer than the others.

If we look at the disassembled class files, available on my github, we can see that the firsts 3 scenarios are almost compiled to the same instructions (there is actually some very small differences that don’t affect the performances). All of them will call the iterator method of the List and then use the hasNext and next methods. The generated class file for the two lasts scenario are also almost identical. We can see that LinkedList is very bad at getting random elements with get(int) and in this case, it is better to use the iterator method.

Conclusion

Basically there is two strategy : using the fact that a collection implements Iterable or using some methods specific to the implementation (like get(int for a List)).

In my opinion, you should ALWAYS use the iterator method because :

  • It can be used with all collections; If you want to change a List by a Set, you can!
  • All collections implementations have their own optimized version of the Iterator, it should always be the most (or near) efficient way to iterate through the collection

Then choosing between the while, for or for each version is just a matter of taste, it won’t change anything to the functionality.

Also if you need a loop counter you can do :

int sum = 0;
int i =0;
for (Iterator<Integer> it = list.iterator(); it.hasNext(); i++) {
   sum += it.next();
}

 

For more details about the class files generated, I have posted a disassembled version of the class files on my github, next to the code.

This entry was posted in Java Core. Bookmark the permalink.

One thought on “For, for each, while : What is the difference?

  1. If you feel the need to use increments for list iteration, at least see if your list implements RandomAccess. Sun introduced that so code can distinguish between LinkedList-like objects from ArrayList-like objects.

    On the other hand, there is one application where you must use Iterator objects: deleting from lists. Never do:

    for (int i = 0; i < list.size(); i++) {
    if (shouldRemove(list.get(i))) {
    list.remove(i);
    }
    }

    Do
    Iterator it = list.iterator();
    while (it.hasNext()) {
    if (shouldRemove(it.next())) {
    it.remove();
    }
    }

    The first will cause ConcurrentModificationExceptions and other logical errors.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>