Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Question about performance and optimization

Tags:

java

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;
    }
}
like image 458
gregory561 Avatar asked Mar 12 '26 11:03

gregory561


2 Answers

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).

like image 167
SJuan76 Avatar answered Mar 14 '26 02:03

SJuan76


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.

like image 26
NPE Avatar answered Mar 14 '26 02:03

NPE



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!