continue first? or Should the code just go ahead?
Example:
for (int a : array) {
if (map.containsKey(a))
continue;
~~~
}
//or
for (int a : array) {
if (!map.containsKey(a)) {
~~~
}
}
Which phrase is faster? Or is there no difference in performance? Then what's the reason?
In Java, you can also add labels to the continue
statement. In fact, continue
is actually a syntactic sugar for a goto LABEL
statement with LABEL
pointing to the top of the most inner loop.
for (int a : array) {
if (map.containsKey(a))
continue;
// ...
}
Is equivalent to:
label1:
for (int a : array) {
if (map.containsKey(a))
continue label1;
// ...
}
When compiled, both produce the same bytecode. Actually, when decompiling their respective .class
file of either one, you'll see the decompiler converting them into your second version:
for (int a : array) {
if (!map.containsKey(a)) {
// ...
}
Besides the readability reason mentioned that you get your code one nested level less, there is no noticeable performance difference between the 2.
The presence of the continue
statement in the language syntax is not even necessary. Most probably, it remained for backward compatibility reasons. By contrast, the Scala language doesn't offer a continue
statement in the standard library, simply because there is nothing that continue
offers that you can't do with a Boolean value that changes when some condition is not met anymore.
Here's how javap
disassembles your examples. I added a println
statement instead of ~~~
:
Using continue
:
74: iload 5
76: iload 4
78: if_icmpge 118
81: aload_3
82: iload 5
84: iaload
85: istore 6
87: aload_1
88: iload 6
90: invokestatic #10 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
93: invokeinterface #22, 2 // InterfaceMethod java/util/Map.containsKey:(Ljava/lang/Object;)Z
98: ifeq 104
101: goto 112
104: getstatic #26 // Field java/lang/System.out:Ljava/io/PrintStream;
107: iload 6
109: invokevirtual #32 // Method java/io/PrintStream.println:(I)V
112: iinc 5, 1
115: goto 74
Without using continue
:
74: iload 5
76: iload 4
78: if_icmpge 115
81: aload_3
82: iload 5
84: iaload
85: istore 6
87: aload_1
88: iload 6
90: invokestatic #10 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
93: invokeinterface #22, 2 // InterfaceMethod java/util/Map.containsKey:(Ljava/lang/Object;)Z
98: ifne 109
101: getstatic #26 // Field java/lang/System.out:Ljava/io/PrintStream;
104: iload 6
106: invokevirtual #32 // Method java/io/PrintStream.println:(I)V
109: iinc 5, 1
112: goto 74
They look almost identical. Notice in the first version, using continue
translates into a goto
statement.