19

I wonder if there is a difference between these:

ArrayList<Example> list = new ArrayList<Example>

1-)

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

2-)

for(Example example : list) {
    example.doSomething();
}

If there is not any difference which one is more common or efficient?

Jaroslaw Pawlak
  • 5,538
  • 7
  • 30
  • 57
shanks
  • 342
  • 2
  • 4
  • 16
  • Difference in what sense? – Maroun Nov 07 '15 at 11:13
  • Premature optimization: Don't. Just... Don't. If you don't have a speed problem, don't solve it. In 99,9% of all cases, you will not notice a difference between the two - except the obvious, with one you have an index (and no iterator) and it only works on methods with a get(x) method, while the other you have no index, an iterator and it works with any collection. – Florian Schaetz Nov 07 '15 at 11:14
  • The second one is more efficient. Because every .get(i) starts a random access search. – Reinard Nov 07 '15 at 11:14
  • @Reinard Potentially yes, depending on the list being iterated through. The `ArrayList` in the example has no speed difference, but a `LinkedList` would show noticeable differences. – Kayaman Nov 07 '15 at 11:17
  • @Kayaman it all depends on the exact case which is running ofc. – Reinard Nov 07 '15 at 11:37
  • @FlorianSchaetz I agree premature optimisation is very bad. But it doesn't mean that we have to write bad code in the first place. If you are using a `LinkedList`, you should use a for-each loop instead of using a traditional one, justifying it with saying "no premature optimisations". Spending 3-5 seconds on thinking upfront about such small things doesn't hurt as much as a whole week of profiling in the future. – Jaroslaw Pawlak Nov 07 '15 at 11:43
  • 2
    @JaroslawPawlak You should **always** use a for-each loop, unless you need the index for some reason. (Or in Java 8, you can use streams.) And not because it's faster (it usually isn't) but because it's easier to read. – biziclop Nov 07 '15 at 12:06

4 Answers4

29

Traditional loop

for (int i = 0; i < list.size(); i++) {
    list.get(i).doSomething();
}
  • allows to modify the list, e.g.:
    • you can add extra element at the end of list and it will be also iterated through
  • you know the index
    • can be used to refer to another list of the same size
    • can be used to refer to previous/next element
  • efficient only in RandomAccess lists
    • in case of LinkedList in every iteration of the loop, get(i) will have to iterate over all elements starting from head/tail to i
  • works only with List since List#get(int) is used
  • error prone, a lot of things that can go wrong, e.g.:
    • i = 0; instead of int i = 0; - will refer to variable declared before the loop, possible side effects outside of the loop
    • > instead of < - loop will not execute
    • j++ instead of i++ - infinite loop
    • .get(j) instead of .get(i) - will always get the same element

For-each loop

for (Example example : list) {
    example.doSomething();
}
  • does not allow to modify the list
    • trying to do so will most likely result in ConcurrentModificationException
  • you don't know the index of the element
    • you cannot refer to previous/next element
  • efficient in all cases because uses Iterator specific for the collection
    • efficient in case of LinkedList
  • works not only with every Collection, but with every Iterable since Iterable#iterator() is used
    • you can easily replace List with a Set - no changes to the loop required
    • you can easily replace with your own class, it just has to implement Iterable
  • more robust (less code, fewer special characters)

Summary

for-each loop wins with a score 3 : 2.

The only reason to use a traditional loop is when:

  • the index of element is required, or
  • the list has to be modified
Jaroslaw Pawlak
  • 5,538
  • 7
  • 30
  • 57
3

They are basically the same, but for-each (the second one) has certain restrictions.

  1. It can be used for accessing the array elements but not for modifying them.

  2. It is not usable for loops that must iterate over multiple collections in parallel—for example, to compare the elements of two arrays.

  3. It can be used only for a single element access and cannot be used to compare successive elements in an array. It is a forward-only iterator. If you want to access only a few elements of the array, you would need to use the traditional for loop.

Mohammed Aouf Zouag
  • 17,042
  • 4
  • 41
  • 67
  • @Point 1: you can modify the array elements by calling mutable methods. (or you need to specify, what you mean with "modify") I guess what you mean is that one cannot modify the array (or `Iterable`) itself. – Tom Nov 07 '15 at 11:28
1

The second one works with every type of (potentially unordered) Iterable, as it doesn't rely on random access, i.e. get(i).

Sebastian S
  • 4,420
  • 4
  • 34
  • 63
1

for(:) statement is a read-only loop. You cannot change a collection within this loop. Also you cannot use more than one element.

The traditional for statement doesn't have such limits.

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142