110

Today I was happily coding away when I got to a piece of code I already used hundreds of times:

Iterating through a Collection (here ArrayList)

For some reason, I actually looked at the autocompletion options of Eclipse and it got me wondering:

What cases are the following loops better to use than the others?

The classic array index loop:

for (int i = 0; i < collection.length; i++) {
  type array_element = collection.get(index);
}

The Iterator hasNext()/next():

for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
  type type = (type) iterator.next();   
}

And my favorite because its so simple to write:

for (iterable_type iterable_element : collection) {

}
HDJEMAI
  • 9,436
  • 46
  • 67
  • 93
Jason Rogers
  • 19,194
  • 27
  • 79
  • 112

6 Answers6

113

The first one is useful when you need the index of the element as well. This is basically equivalent to the other two variants for ArrayLists, but will be really slow if you use a LinkedList.

The second one is useful when you don't need the index of the element but might need to remove the elements as you iterate. But this has the disadvantage of being a little too verbose IMO.

The third version is my preferred choice as well. It is short and works for all cases where you do not need any indexes or the underlying iterator (i.e. you are only accessing elements, not removing them or modifying the Collection in any way - which is the most common case).

MAK
  • 26,140
  • 11
  • 55
  • 86
  • 4
    +1 Beat me to it. was going to mention LinkedList (not **all** `Collection`'s are cheap to retrieve by index). – The Scrum Meister Mar 08 '11 at 05:32
  • As long as one required to just loop elements, it's always good to use 3rd version, because implementation is already exists for all the different Collections and Sun or any JDK implementation strives to improve the performance rather than every one. – Phani Mar 08 '11 at 05:51
  • @Phani: The other two variants also work on any JDK implementation as well. – MAK Mar 08 '11 at 05:56
  • I didn't say that those wouldn't work, but if by any chance a certain improvements or performance changes are done for the implementations of collections, then it would automatically apply for your code and you don't need to write to improve performance is what I mean. – Phani Mar 08 '11 at 06:05
  • 1
    @Phani: AFAIK the 3rd form is merely syntactic sugar for the 2nd form (i.e. under the hood the foreach variant actually uses an iterator). So any performance benefits should be available to both variants. The first version of course would not get any performance benefits (e.g. if the `List` is implemented as a tree, it would actually be slower). – MAK Mar 08 '11 at 09:12
39

All of them have there own uses:

  1. If you have an iterable and need to traverse unconditionally to all of them:

    for (iterable_type iterable_element : collection)

  2. If you have an iterable but need to conditionally traverse:

    for (Iterator iterator = collection.iterator(); iterator.hasNext();)

  3. If data-structure does not implement iterable:

    for (int i = 0; i < collection.length; i++)

Suraj Chandran
  • 24,433
  • 12
  • 63
  • 94
  • Can you do this to traverse the first method conditionally: if (iterable_element.some_attribute) { // do something; } else { // do nothing; }. If yes then there's essentially no difference between the first and second method, other than syntactic sugar. – Thomas Nguyen Jun 11 '15 at 01:25
  • 1 is just as able to conditionally traverse as the others using `break` and/or `continue` – arcyqwerty Jul 14 '17 at 00:09
16

There is additionally collections’ stream() util with Java 8

collection.forEach((temp) -> {
            System.out.println(temp);
});

or

collection.forEach(System.out::println);

More information about Java 8 stream and collections for wonderers link

4

None of them are "better" than the others. The third is, to me, more readable, but to someone who doesn't use foreaches it might look odd (they might prefer the first). All 3 are pretty clear to anyone who understands Java, so pick whichever makes you feel better about the code.

The first one is the most basic, so it's the most universal pattern (works for arrays, all iterables that I can think of). That's the only difference I can think of. In more complicated cases (e.g. you need to have access to the current index, or you need to filter the list), the first and second cases might make more sense, respectively. For the simple case (iterable object, no special requirements), the third seems the cleanest.

Rafe Kettler
  • 75,757
  • 21
  • 156
  • 151
2

The first option is better performance wise (As ArrayList implement RandomAccess interface). As per the java doc, a List implementation should implement RandomAccess interface if, for typical instances of the class, this loop:

 for (int i=0, n=list.size(); i < n; i++)
     list.get(i);

runs faster than this loop:

 for (Iterator i=list.iterator(); i.hasNext(); )
     i.next();

I hope it helps. First option would be slow for sequential access lists.

2

Here is an example

Query query = em.createQuery("from Student");
             java.util.List list = query.getResultList();
             for (int i = 0; i < list.size(); i++) 
             {

                 student = (Student) list.get(i);
                 System.out.println(student.id  + "  " + student.age + " " + student.name + " " + student.prenom);

             }
Abdelouhab
  • 179
  • 3
  • 13