Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any difference between these two loops?

Is there any difference performance-wise between the two code snippets below?

for(String project : auth.getProjects()) {
    // Do something with 'project'
}

and

String[] projects = auth.getProjects();
for(String project : projects) {
    // Do something with 'project'
}

For me, I think the second one is better, but it is longer. The first one is shorter, but I am not really sure if it is faster. I am not sure, but to me it seems like every time that loop is iterated, auth.getProjects is called. Is that not so?

like image 712
hamid Avatar asked May 04 '14 04:05

hamid


3 Answers

Edit: @StephenC is right, the JLS is a much better place to find an answer for something of this nature. Here is a link to the enhanced for loop in the language specification. In there you will find that there are a few different types of for statements it generates but none of them would call the method more than 1 time.


Simple test shows that the method is only called once

public class TestA {
    public String [] theStrings;

    public TestA() {
        theStrings = new String[] {"one","two", "three"};
        for(String string : getTheStrings()) {
            System.out.println(string);
        }
    }

    public String[] getTheStrings() {
        System.out.println("get the strings");
        return theStrings;
    }

    public static void main(String [] args) {
        new TestA();
    }
}

Output:

get the strings
one
two
three

So essentially they are the same thing. The only thing that may be beneficial about the 2nd would be if you want to use the array outside the for loop.


Edit

You got me curious about how the java compiler handled this so using the code above I decompiled the class file and heres what the result is

public class TestA
{

    public TestA()
    {
        String as[];
        int j = (as = getTheStrings()).length;
        for(int i = 0; i < j; i++)
        {
            String string = as[i];
            System.out.println(string);
        }

    }

    public String[] getTheStrings()
    {
        System.out.println("get the strings");
        return theStrings;
    }

    public static void main(String args[])
    {
        new TestA();
    }

    public String theStrings[] = {
        "one", "two", "three"
    };
}

As you can see the compiler simply restructured your for loop into a standard loop! It also further proves that in fact they are exactly the same after the compiler gets through with it.

like image 190
ug_ Avatar answered Sep 22 '22 04:09

ug_


Assumng that by in you mean :, there is no difference in performance; they both do the same thing. Even in the first example, auth.getProjects() is executed only once; it can't be executed multiple times, since if it was, the for iteration would have to start over each time, which is not how it works.

I'd recommend using the version you find to be clearer.

like image 27
Warren Dew Avatar answered Sep 20 '22 04:09

Warren Dew


There are a few more operations in the second example. Instead of referencing the array directly using the method, you are declaring a new reference variable, storing it in that new variable, then referencing the new variable.

You can check out the bytecode with ASM Bytecode Outline.

BUT, this is micro-optimization. If you need a new reference variable, then create one. If you don't need one, save the work and don't create a new one.

like image 26
Vince Avatar answered Sep 18 '22 04:09

Vince