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.