Question

I've using the "foreach" loop in my Java applications for a long time. Recently I started wondering if there is any significative difference in performance (or even in the result) between:

Collection<String> collection = someMethod();
for(String element : collection) { ... }

and:

for(String element : someMethod()) { ... }

What if instead of a Collection it is a List, a Map, a Set or an array?

Was it helpful?

Solution 3

It's a semantic difference, you won't see any real performance change in your code as a result of assigning a method return value to a local variable. Lists, Sets, Map entry sets, arrays are all iterable in the for-each loop, so they are all fine and result in you not having to know the return collection type.

OTHER TIPS

The difference between both codes can be seen in their generated bytecodes.

The first one has extra two instructions over the second one; it stores the return value of someMethod() on the local stack and then loads it again for accessing it's iterator.

However the second one immediately uses the Iterator without storing the return value of someMethod() on the local stack.

Below code shows the elimination of 3: and 4: instructions.

First:

Collection<String> collection = someMethod();
for(String element : collection) { ... }

     0: invokestatic  #3                  // Call someMethod()
     3: astore_1                          // Store the result as first item on local stack
     4: aload_1                           // Load the Collection again into operand stack
     5: invokeinterface #4,  1            // Get Iterator (of Collection) - InterfaceMethod java/util/Collection.iterator:()Ljava/util/Iterator;
    10: astore_2                          // Store Iterator on local stack #2
    11: aload_2                           // LOOP STARTS - Load iterator
    12: invokeinterface #5,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
    17: ifeq          33
    20: aload_2       
    21: invokeinterface #6,  1            // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
    26: checkcast     #7                  // class java/lang/String
    29: astore_3      
    30: goto          11                  // LOOP ENDS
    33: return

Second

for(String element : someMethod()) { ... }

     0: invokestatic  #3                  // Call someMethod() 
     3: invokeinterface #4,  1            // Get Iterator (of Collection) - Interface Method java/util/Collection.iterator:()Ljava/util/Iterator;/
     8: astore_1                          // Store Iterator on local stack #2  
     9: aload_1                           // LOOP STARTS - Load iterator
    10: invokeinterface #5,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
    15: ifeq          31
    18: aload_1       
    19: invokeinterface #6,  1            // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
    24: checkcast     #7                  // class java/lang/String
    27: astore_2      
    28: goto          9                   // LOOP ENDS
    31: return       

BTW, I don't think that they will have a big difference in terms of performance since both have 9 instructions inside the loop.

There is no visible performance difference between the two. The first way is more elegant and readable than the second one. But from performance point of view its not a deterrent. Both produce identical bytecode for the 'inside the loop' part.

For compatibility you shall use the second and if you know the result is never null.

The first shall not be used if you dont need the collection anymore.

I prefer a third suggestion:

Collection<String> collection = someMethod();
if (collection != null) {
    for(String element : collection) { ... }
}

Regards.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top