why is the enhanced for loop more efficient than the normal for loop

39,155

Solution 1

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.

Solution 2

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 case1:10 inputs
test case2:30 inputs
test case3:50 inputs
test case4:100 inputs
test case5:150 inputs
test case6:300 inputs
test case7:500 inputs
test case8:1000 inputs
test case9:2000 inputs
test case10:5000 inputs
test case11:10000 inputs
test case12: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

Solution 3

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.

Solution 4

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.

Solution 5

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.

Share:
39,155
Archie.bpgc
Author by

Archie.bpgc

Updated on February 12, 2020

Comments

  • Archie.bpgc
    Archie.bpgc over 4 years

    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?