According to Java documentation : / p>
The Java compiler generally generates more efficient bytecode from switch statements that use String objects than from chained if-then-else statements.
According to Java documentation : / p>
The Java compiler generally generates more efficient bytecode from switch statements that use String objects than from chained if-then-else statements.
The main reason in this case is that it does not compare the strings with equals()
and yes with hashCode()
. After compiling each case
will save the hash of the string and not the string itself. It then generates the hash of the variable being used in switch
and compares these integer values which is much faster than comparing a string.
This allows for a gain in search because switch
uses a lookup table instead of going through each condition. The if
is O (N) and the switch
is usually O (1).
Bytecode compared ( removed from this answer in SO ):
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
}
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
}
Although the code is larger, it runs faster because it does not have to go through all of it like the previous one.
Note that there is a comparison of string to confirm if there was no hash collision but it is executed only for the case that hashed hash equal and not for all conditions. Obviously the difference is most noticeable when there are several case
s. With few, there may even be loss of performance. Of course this will also depend on the order of what needs to be found. If the first if
satisfies the condition is probably faster than switch
(I can not guarantee because it depends on implementation).
Another thing that can make if
faster is if the string is too short. A direct comparison turns out to be faster than having to hash and then comparing your result.