Reputation: 886
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
?
Upvotes: 0
Views: 599
Reputation: 410
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.
Upvotes: 3
Reputation: 2040
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.
Upvotes: 1
Reputation: 1902
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.
Upvotes: 2
Reputation: 11483
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.
Upvotes: 1