gregory561
gregory561

Reputation: 15046

Question about performance and optimization

How inefficient is that:

List<Object> getList(){
    return new LinkedList<Object>();
}

void foo(){
    for(Object o: getList()){
       do something with o;
    }
}

in compare with that:

List<Object> getList(){
    return new LinkedList<Object>();
}

void foo(){
    List<Object>  os = getList();
    for(Object o: os){
       do something with o;
    }
}

Upvotes: 2

Views: 136

Answers (4)

SJuan76
SJuan76

Reputation: 24780

In

for(Object o: getList()) {

getList() is an expression that is evaluated once and its result (a reference an iterator of the list) kept. If you fear that this code calls getList() at each iteration, it is not true (if it was, it would be an infinite loop if the list had at least one element as each time the iteration would start with a new list, at the 0 element).

Upvotes: 5

NPE
NPE

Reputation: 500267

There won't be any perceptible difference.

I've compiled the following code:

import java.util.LinkedList;
import java.util.List;

public class Test1 {

    static List<Object> getList(){
        return new LinkedList<Object>();
    }

    void process(Object o) {}

    void foo1(){
        for(Object o: getList()){
            process(o);
        }
    }

    void foo2(){
        List<Object>  os = getList();
        for(Object o: os){
            process(o);
        }
    }
}

The bytecodes for foo1 and foo2 are as follows:

void foo1();
  Code:
   0:   invokestatic    #26; //Method getList:()Ljava/util/List;
   3:   invokeinterface #28,  1; //InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
   8:   astore_2
   9:   goto    24
   12:  aload_2
   13:  invokeinterface #34,  1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
   18:  astore_1
   19:  aload_0
   20:  aload_1
   21:  invokevirtual   #40; //Method process:(Ljava/lang/Object;)V
   24:  aload_2
   25:  invokeinterface #42,  1; //InterfaceMethod java/util/Iterator.hasNext:()Z
   30:  ifne    12
   33:  return

void foo2();
  Code:
   0:   invokestatic    #26; //Method getList:()Ljava/util/List;
   3:   astore_1
   4:   aload_1
   5:   invokeinterface #28,  1; //InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
   10:  astore_3
   11:  goto    26
   14:  aload_3
   15:  invokeinterface #34,  1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
   20:  astore_2
   21:  aload_0
   22:  aload_2
   23:  invokevirtual   #40; //Method process:(Ljava/lang/Object;)V
   26:  aload_3
   27:  invokeinterface #42,  1; //InterfaceMethod java/util/Iterator.hasNext:()Z
   32:  ifne    14
   35:  return

As you can see for yourself, the bytecodes for the two loops are identical. The only difference is that foo2 stores and loads the list reference in a local variable at the start.

One might argue that a better optimizing compiler may be able to eliminate os altogether, producing identical code for both functions.

Upvotes: 4

Petar Ivanov
Petar Ivanov

Reputation: 93020

In fact the former is more efficient in theory, because in the latter there is one more reference created.

However this is negligible (really negligible) difference.

Upvotes: 0

Jacob
Jacob

Reputation: 43219

As this:

List<Object>  os = getList();

only creates a reference and the actual data is not copied, the difference in speed is negligible, perhaps non-existant because it probably will be the same bytecode.

Upvotes: 4

Related Questions