0

So my introduction to for each loops has been somewhat of a love and hate relationship. At times, I see their utility as invaluable to iterate over and ArrayList of Objects (etc.) and just loop through and call the method for the given object class on them. But, I want to know what the limitations and best practice of using for each versus regular for loops that go over each individual element of the ArrayList or Array.

Nothing, the question is open ended. If anything, I'm looking to see what the best practices and use cases are when handling each specific loop structure.

  • I use foreach loops unless I need indexed access within the loop body. In that case I use indexed for loops. – michid Apr 01 '23 at 19:53
  • The two loops are not comparable because by design they do not work in the same way. A forEach loop is syntactic sugar for using an `Iterator`. The main practical difference to the programmer is a forEach loop doesn't have a convenient, scoped index variable - usually `i`. If you need the index, use plain `for`. If you don't, and like most coders you're using ArrayLists, use forEach. – Bohemian Apr 01 '23 at 21:34
  • Most code I have seen uses the enhanced `for` loop when possible, the normal `for` loop otherwise. – MC Emperor Apr 01 '23 at 22:54

1 Answers1

0

If you are iterating a class implementing the List interface the regular for loop will get the next element with list.get(I), the for each will internally use an Iterator and call iterator.next(). This has a a huge impact on the speed of a loop with some classes.

A small example:

LinkedList<Integer> list = new LinkedList<>();
for (int i = 0; i < 100_000; i++) list.add(i);
int doNothing = 0;
long start1 = System.nanoTime(), end1;
for (int i = 0; i < list.size(); i++) doNothing+= list.get(i);
end1 = System.nanoTime();
System.out.println(end1-start1);
doNothing = 0;
long start2 = System.nanoTime(), end2;
for(Integer i : list) doNothing+= i;
end2 = System.nanoTime();
System.out.println(end2-start2);

the output on my machine:

3460558170   //nanoseconds regular
2178261      //nanoseconds for each ~1000 times as fast in this specific example

The reason why the for each loop is that much faster is, that when it has the first element, it directly jumps to the next one and processes the next node. In LinkedList class each inserted object represented by a node that remembers the next node. So it performs in O(n).

foreach uses iterator
*
*
*
*
*

In a a normal loop when list.get(i) is called it will start from the beginning and jump from node to node i times. When the list is long, it will take some time. When this is done in a loop, the performance is in O(n²).

regular for list.get(i)
*
**
***
****
*****

Sometimes you have the case that you just know, that a List - Interface is returned by a method call. If it returns a long LinkedList and you use a normal fori the inpact on the performance could be huge.

Try the code I posted and vary the length of the list to check the difference.

mad_mosel
  • 35
  • 8
  • 1
    This is *not* a fair comparison between *loop types*. No one is going to call `list.get(i)` on a LinkedList when iterating over all elements. Use ArrayList instead. – Bohemian Apr 01 '23 at 21:19
  • 1
    BTW2 "*ArrayList .... will perform better using the for each loop*" is more probably the opposite (the iterator most certainly is also using an index itself) || BTW3 micro-benchmarking is not that trivial in Java (see for example [How do I write a correct micro-benchmark in Java?](https://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java)) – user16320675 Apr 01 '23 at 21:29
  • @user16320675 Thanks again - checked the code of ArrayList in OpenJDK 17 - the data is stored in an Object[] array. will update – mad_mosel Apr 01 '23 at 21:56
  • @Bohemian I used LinkedList to demonstrate that there can be a difference. So, I chose data structure with the most obvious difference. I hope this helps with question. – mad_mosel Apr 01 '23 at 22:35