Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 830
Archie.bpgc Avatar asked Jul 19 '12 06:07

Archie.bpgc


People also ask

What are the advantages of enhanced for loop over normal for loop?

The advantage of the for-each loop is that it eliminates the possibility of bugs and makes the code more readable. It is known as the for-each loop because it traverses each element one by one. The drawback of the enhanced for loop is that it cannot traverse the elements in reverse order.

Are enhanced for loops more efficient?

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.

When should you use an enhanced for loop?

You can use it whenever you need to loop through all the elements of an array and don't need to know their index and don't need to change their values. It starts with the first item in the array (the one at index 0) and continues through in order to the last item in the array.


6 Answers

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.

like image 57
Joachim Sauer Avatar answered Oct 16 '22 16:10

Joachim Sauer


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

like image 22
Philip George Avatar answered Oct 16 '22 14:10

Philip George


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.

like image 7
Peter Lawrey Avatar answered Oct 16 '22 14:10

Peter Lawrey


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.

like image 3
Thilo Avatar answered Oct 16 '22 16:10

Thilo


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.

like image 3
JB Nizet Avatar answered Oct 16 '22 15:10

JB Nizet


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.

like image 1
Basheer AL-MOMANI Avatar answered Oct 16 '22 16:10

Basheer AL-MOMANI