33

I read that the enhanced for loop is more efficient than the normal for loop here:

http://developer.android.com/guide/practices/performance.html#foreach

When I searched for the difference between their efficiency, all I found is: In case of normal for loop we need an extra step to find out the length of the array or size etc.,

for(Integer i : list){
   ....
}


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

But is this the only reason, the enhanced for loop is better than the normal for loop? In that case better use the normal for loop because of the slight complexity in understanding the enhanced for loop.

Check this for an interesting issue: http://www.coderanch.com/t/258147/java-programmer-SCJP/certification/Enhanced-Loop-Vs-Loop

Can any one please explain the internal implementation of these two types of for loops, or explain other reasons to use the enhanced for loop?

user unknown
  • 35,537
  • 11
  • 75
  • 121
Archie.bpgc
  • 23,812
  • 38
  • 150
  • 226
  • 4
    If you "read something" somewhere, it's best to cite it when possible. – cheeken Jul 19 '12 at 06:59
  • i read it here...but there was not any explanation why it is so: http://developer.android.com/guide/practices/performance.html#foreach – Archie.bpgc Jul 19 '12 at 07:01
  • 2
    "To summarize: use the enhanced for loop by default, but consider a hand-written counted loop for performance-critical ArrayList iteration." That says the opposite of what you read: For ArrayList, the second alternative is faster. – Thilo Jul 19 '12 at 07:03
  • @Archie.bpgc: actually, there **is** an explanation: "`zero()` is slowest, because the JIT can't yet optimize away the cost of getting the array length once for every iteration through the loop.". That looks like an explanation to me. – Joachim Sauer Jul 19 '12 at 07:24
  • leave the zero()...its the worst way of looping...but what about one()?? my question is one() and two() have no difference while looping through arrays(in case of java)...but in android better i use two() even for arrays?? – Archie.bpgc Jul 19 '12 at 07:30
  • THe linked article talks about arrays. THe posh for loop on arrays works entirely differently to that on lists (iterables). – Tom Hawtin - tackline Jul 19 '12 at 07:43

7 Answers7

58

It's a bit of an oversimplification to say that the enhanced for loop is more efficient. It can be, but in many cases it's almost exactly the same as an old-school loop.

The first thing to note is that for collections the enhanced for loop uses an Iterator, so if you manually iterate over a collection using an Iterator then you should have pretty much the same performance than the enhanced for loop.

One place where the enhanced for loop is faster than a naively implemented traditional loop is something like this:

LinkedList<Object> list = ...;

// Loop 1:
int size = list.size();
for (int i = 0; i<size; i++) {
   Object o = list.get(i);
   /// do stuff
}

// Loop 2:
for (Object o : list) {
  // do stuff
}

// Loop 3:
Iterator<Object> it = list.iterator();
while (it.hasNext()) {
  Object o = it.next();
  // do stuff
}

In this case Loop 1 will be slower than both Loop 2 and Loop 3, because it will have to (partially) traverse the list in each iteration to find the element at position i. Loop 2 and 3, however will only ever step one element further in the list, due to the use of an Iterator. Loop 2 and 3 will also have pretty much the same performance since Loop 3 is pretty much exactly what the compiler will produce when you write the code in Loop 2.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • 3
    @Joachim, the difference, eventually seems to Random access and Serial access of the collection in the example quoted. For an array, both the loop types will behave the same. – Santosh Jul 19 '12 at 07:21
  • but in the link here http://developer.android.com/guide/practices/performance.html#foreach3..he gives the example of an Array...so according to you explanation we dont need to use foreach when traversing an array right?? – Archie.bpgc Jul 19 '12 at 07:21
  • 1
    @Archie.bpgc: first of all: Android is different from "Java". The Dalvik VM is not (yet) as good at optimizing as the HotSpot VM, so there will be some places where performance suggestions for Android differ from "normal" Java. This is one such case. Read the documentation precisely: especially the examples `one`, `two` and `three` will *probably* be quite similar in performance on a "normal" JVM. – Joachim Sauer Jul 19 '12 at 07:24
  • but in android better i use the 3rd approach even for arrays?? – Archie.bpgc Jul 19 '12 at 07:25
  • 1
    @Archie.bpgc: yes, for Android the example `three` is the best one for arrays. For `ArrayList` (and probably other random-access `List` implementations) this guideline tells you *not* to use the enhanced for-loop however (probably to avoid the `Iterator` allocation overhead). – Joachim Sauer Jul 19 '12 at 07:35
  • again you are saying "For ArrayList (and probably other random-access List implementations) this guideline tells you not to use the enhanced for-loop however (probably to avoid the Iterator allocation overhead)." but an array is a random accessible data structure right?? – Archie.bpgc Jul 19 '12 at 07:43
  • @Archie.bpgc: yes, but an array and an `ArrayList` are two **entirely** different things. – Joachim Sauer Jul 19 '12 at 07:44
  • For small lists, loop 1 will be fastest. – Tom Hawtin - tackline Jul 19 '12 at 07:44
  • @JoachimSauer According to Effective Java loop2 is going to be the most optimized one but I am not sure about the reason though. Please see my answer and throw any comment if you know why . – Geek Jul 19 '12 at 09:55
  • @JoachimSauer I am not sure about this statement of yours -"*Loop 2 and 3, however will only ever step one element further in the list, due to the use of an Iterator.*", because if I see the implementation of the Iterator then it does the same thing, it also uses an index and call get method of the list, then how it would be different than simple FOR loop? – hagrawal7777 Apr 24 '17 at 20:36
  • @hagrawal: the iterator of a linked list (for example) will not be implemented using an index, but using a pointer to the current object instead, so "get next objects" takes constant time. **If** one implemented an iterator for a linked list using just an index, then yes, it would be just as bad, but no one does that. – Joachim Sauer Apr 26 '17 at 10:39
12

I am myself surprised in a little experiment i did today with above mentioned points. So what i did was that i inserted a certain number of elements to a linked list and iterated through it using the above mentioned three methods 1)using advanced for loop 2) using Iterator 3) using simple loop and get()
I guess programmers such as you guys can better understand what i did by seeing the code.

long advanced_timeElapsed,iterating_timeElapsed,simple_timeElapsed;
long first=System.nanoTime();
for(Integer i: myList){
  Integer b=i;
}
long end= System.nanoTime();
advanced_timeElapsed=end-first;
System.out.println("Time for Advanced for loop:"+advanced_timeElapsed);

first=System.nanoTime();
Iterator<Integer> it = myList.iterator();
while(it.hasNext())
{
  Integer b=it.next();
}
end= System.nanoTime();
iterating_timeElapsed=end-first;
System.out.println("Time for Iterating Loop:"+iterating_timeElapsed);
        first=System.nanoTime();

int counter=0;
int size= myList.size();
while(counter<size)
{
  Integer b=myList.get(counter);
  counter++;    
}
end= System.nanoTime();
simple_timeElapsed=end-first;
System.out.println("Time for Simple Loop:"+simple_timeElapsed);

The results where not what i expected . Following is the graph of time elapsed in 3 cases. Time Elapsed Graph

Y axis-time elapsed X axis-test case

test-case inputs
1 10 inputs
2 30 inputs
3 50 inputs
4 100 inputs
5 150 inputs
6 300 inputs
7 500 inputs
8 1000 inputs
9 2000 inputs
10 5000 inputs
11 10000 inputs
12 100000 inputs

Here you can see that simple loop performs way better than others.if you find any errors in the code above , do reply and i will check again. will update on this further after i dig through bytecode and see what is happening under the hood. My apologies for such a long response but i like to be descriptive. Philip

f.khantsis
  • 3,256
  • 5
  • 50
  • 67
Philip George
  • 406
  • 5
  • 7
  • So it came down to this case1)advanced for loop is simply and implementation of iterator. it creates an iterator obect. performs the hasNext() and executes next() of iterator to get the next element. so in effect it is the same as case 2. but it doesn't explain the sharp climb in graph b/w advanced and Iterator. in case 3 works more efficiently because in arraylist, get(index) is random access to an array. so it should perform well – Philip George May 28 '14 at 12:10
  • 3
    Have you ever reordered the test cases? The reason why the first implementation is slower may be due to cache misses (the objects are not yet in the cache)... – Siu Ching Pong -Asuka Kenji- Aug 04 '14 at 19:30
  • Yes , as a matter of fact , i reordered and tried. i dont know if JIT is messing with benchmark. but when i peeked into the bytecode, it sure shows that simple loop works better . – Philip George Aug 05 '14 at 08:25
  • 1
    It depends on data structure. If you use LinkedList you will see completely different picture. – Adil Aliyev Aug 31 '16 at 05:52
7

I read that enhanced for loop is efficient than normal for loop.

Actually sometimes its less efficient for the program, but most of the time its exactly the same.

Its more efficient for the developer, which is often far more important

A for-each loop is particularly useful when iterating over a collection.

List<String> list = 
for(Iterator<String> iter = list.iterator(); list.hasNext(); ) {
    String s = list.next();

is more easily written as (but does the same thing as, so its no more efficient for the program)

List<String> list = 
for(String s: list) {

Using the "old" loop is slightly more efficient when access a randomly accessible collection by index.

List<String> list = new ArrayList<String>(); // implements RandomAccess
for(int i=0, len = list.size(); i < len; i++) // doesn't use an Iterator!

Using a for-each loop on a collection always uses an Iterator which is slightly less efficient for random access lists.

AFAIK, use a for-each loop is never more efficient for the program, but like I said the efficiency of the developer is often far more important.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • can you please explain about the implementation (where they differ) or examples of cases in which one is more efficient than the other?? – Archie.bpgc Jul 19 '12 at 07:00
  • As someone else points out above, a poorly written old school for loop can be less efficient that the new for-each. So now you know of a case where a for-each loop IS more efficient for the program. – Uncle Iroh Mar 01 '14 at 05:33
  • @UncleIroh Using a for-each loop means you are less likely to write something inefficient. However, if you know what you are doing, the byte code for-each generates is exactly the same as you you might write yourself, but is a short hand. From a byte code level there is no way to tell the difference for sure (expect the generated local variable names are a give away). Well written code will be the same in both cases. If you have an ArrayList, an indexed for loop is slightly more efficient than using a for-each, which uses an iterator. – Peter Lawrey Mar 01 '14 at 17:24
3

The for-each uses the Iterator interface. I doubt that it is more efficient than the "old" style. The Iterator also needs to check the size of the list.

It's mostly for readability.

It should be faster for non-random-access collections like LinkedList, but then the comparison is unfair. You would not have used to second implementation (with slow indexed access) anyway.

Thilo
  • 257,207
  • 101
  • 511
  • 656
3

The foreach loop is as efficient as this kind of loop:

for (Iterator<Foo> it = list.iterator(); it.hasNext(); ) {
     Foo foo = it.next();
     ...
}

because it's strictly equivalent.

If you iterate through a list using

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

Then the foreach loop will have an equivalent performance as your loop, but only for ArrayList. In case of a LinkedList, your loop will have abysmal performance, because at each iteratioon, it will have to traverse all the nodes of the list until it gets to the ith element.

The foreach loop (or the loop based on an iterator, which is the same), doesn't have this problem, since the iterator keeps a reference to the current node and simply goes to the next at each iteration. It's the bast choice, because it works fine with all types of lists. It also expresses the intent more clearly, and is safer because you don't risk to increment the index inside the loop, or use the wrong index in case of nested loops.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • you mean they have the same efficiency but when using loops on linked list or something like that...normal for loop traverses recursively, where as foreach loop traverses iteratively?? – Archie.bpgc Jul 19 '12 at 07:08
  • 2
    It's not recursive vs. iterative. It's just that the `get()` operation, on a linked list, consists in starting from the first node, and get the next one until index i. It's a O(n) operation rather than O(1) in the case of an ArrayList. Getting the next element from an iterator is always O(1). Whether the list is an ArrayList or a LinkedList doesn't matter: the performance is as good as it can be. – JB Nizet Jul 19 '12 at 07:14
  • If you're using `LinkedList` (intensively) then you are likely to have abysmal performance anyway. – Tom Hawtin - tackline Jul 19 '12 at 07:41
1

all answers are good,and I think no more answers are needed, but I just want to point out that:

The enhanced for statement can be used only to obtain array elements

it cannot be used to modify elements.

If your program needs to modify elements, use the traditional counter-controlled for statement.

take a look

int[] array = { 1, 2, 3, 4, 5 };
for (int counter = 0; counter < array.length; counter++)
    array[counter] *= 2;

We could not use the enhanced for statement because we’re modifying the array’s elements.

Basheer AL-MOMANI
  • 14,473
  • 9
  • 96
  • 92
0

From Effective Java :

The standard idiom for looping through an array doesn’t necessarily result in redundant checks. Modern JVM implementations optimize them away.

But Josh Bloch doesn't describe how JVM optimizes them.

Geek
  • 26,489
  • 43
  • 149
  • 227
  • Of course he doesn't! It is a textbook on how to write good Java code, not about the internals of the JVM. To understand how an optimizer does thing kind of thing, you need to look in a textbook on compiler writing. And for the specifics of how a Java JIT compiler does it, look at the JVM source code. – Stephen C Jul 21 '12 at 11:32