The main reason in this case is that it does not compare the strings with equals()
rather with hashCode()
. After each compiled case
will guard the hash of string and not the string in itself. There it generates the hash of the variable being used in the switch
and compare these integer values which is much faster than comparing a string of characters (if you have any form of cache of hash code, otherwise it could be worse).
Thus allows there to be a gain in the search because the switch
uses a table of lookup instead of going through each condition. The if
is O(n) and switch
is usually O(1).
Bytecode compared (withdrawn from that reply in the OS):
Compiled from "CompileSwitch.java"
public class CompileSwitch {
public CompileSwitch();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #16 // String C
2: astore_1
3: ldc #18 // String A
5: aload_1
6: invokevirtual #20 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
9: ifne 28
12: ldc #26 // String B
14: aload_1
15: invokevirtual #20 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
18: ifne 28
21: ldc #16 // String C
23: aload_1
24: invokevirtual #20 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
27: pop
28: return
}
###Switch
Compiled from "CompileSwitch.java"
public class CompileSwitch {
public CompileSwitch();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #16 // String C
2: astore_1
3: aload_1
4: dup
5: astore_2
6: invokevirtual #18 // Method java/lang/String.hashCode:()I
9: lookupswitch { // 3
65: 44
66: 56
67: 68
default: 77
}
44: aload_2
45: ldc #24 // String A
47: invokevirtual #26 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
50: ifne 77
53: goto 77
56: aload_2
57: ldc #30 // String B
59: invokevirtual #26 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
62: ifne 77
65: goto 77
68: aload_2
69: ldc #16 // String C
71: invokevirtual #26 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
74: ifne 77
77: return
}
Even though the code is bigger, it runs faster by not having to go through it all like in the previous.
Note that there is a comparison of string to confirm that there was no collision of hash but she is executed only for the case she gave hash equal and not for all conditions.
Obviously the difference becomes more noticeable when there are several case
s. With few there may even be loss of performance. And of course this will also depend on the order of what needs to be found. If the first if
satisfy the condition is probably faster than the switch
(do not guarantee because depends on implementation).
Another reason that can do the if
be faster if the string is very short. A direct comparison ends up being faster than having to generate the hash and then compare your result.