Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the switch statement faster than if else for String in Java 7?

In Java 7 a string object can be in the expression of a switch statement. Can someone explain the below statement from official documentation?

The Java compiler generates generally more efficient bytecode from switch statements that use String objects than from chained if-then-else statements.

like image 858
user1428716 Avatar asked May 31 '12 14:05

user1428716


People also ask

Why is switch case faster than if-else?

A switch statement is significantly faster than an if-else ladder if there are many nested if-else's involved. This is due to the creation of a jump table for switch during compilation. As a result, instead of checking which case is satisfied throughout execution, it just decides which case must be completed.

Is switch faster than if-else Java?

Speed: A switch statement might prove to be faster than ifs provided number of cases are good. If there are only few cases, it might not effect the speed in any case. Prefer switch if the number of cases are more than 5 otherwise, you may use if-else too.

Which is faster switch case or if-else?

As it turns out, the switch statement is faster in most cases when compared to if-else , but significantly faster only when the number of conditions is large. The primary difference in performance between the two is that the incremental cost of an additional condition is larger for if-else than it is for switch .


1 Answers

Java Code

Having two versions of a class, e.g.

With if-then-else:

public class IfThenElseClass {
    public static void main(String[] args) {
        String str = "C";
        if ("A".equals(str)) {

        } else if ("B".equals(str)) {

        } else if ("C".equals(str)) {

        }
    }
}

With switch:

public class SwitchClass {
    public static void main(String[] args) {
        String str = "C";
        switch (str) {
            case "A":
                break;
            case "B":
                break;
            case "C":
                break;
        }
    }
}

Bytecode

Let's take a look at the bytecode. Getting the bytecode for if-then-else version:

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
}

Getting the bytecode for switch version:

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
}

Conclusion

  • In the first version compares the string by calling the equals method for each condition, until it is found.

  • In the second version is obtained first hashCode of the string. Then this is compared with the values ​​hashCode each case. See the lookupswitch. If any of these values ​​is repeated just happens to run the code for the case. Otherwise, call the equals method of the cases tied. This is much faster than ever call the equals method only.

like image 145
Paul Vargas Avatar answered Oct 19 '22 08:10

Paul Vargas