Вопрос по java, if-statement – Почему оператор switch быстрее, чем если бы для String в Java 7?

16

ВJava 7 string объект может быть в выраженииswitch заявление. Может кто-нибудь объяснить нижеприведенное утверждениеофициальная документация?

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

Какую часть утверждения вы не понимаете? Jon Skeet
Конечно. Это означает следующее: если вы сравниваете строки в большом наборе операторов if-than-else, вы должны использовать вместо этого switch ControlAltDel
Версия не для конкретной строки:stackoverflow.com/questions/2086529/… Ciro Santilli 新疆改造中心 六四事件 法轮功

Ваш Ответ

4   ответа
2

Это более эффективно, например:

switch(yourString) {
    case "text1":
        // your code
        break;
    case "text2":
        // etc.
}

чем корреспондент:

if (yourString.equals("text1")) {
     // your code
} else if (yourString.equals("text2")) {
     // etc.
}
-1

Я предполагаю, что это означает, или что я понимаю, это то, что байт-код (когда вы компилируете свой Java-класс), созданный из оператора switch с использованием строки, быстрее и эффективнее, чем байт-код, созданный из оператора if-else с использованием строки. оба могут выполнять одну и ту же работу, битовый переключатель, по-видимому, более эффективен.

switch (str) {
            case "A":  
                     // do something
                     break;
            case "B":
                     // do something
                     break;
            default: 
                     //do something
                     break;
}

лучше, чем

if(str.equals("A")) {
//do something
} else if(str-equals("B")) {
//do something
} else {
//do something
}
38
Java Code

С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)) {

        }
    }
}

С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

Давайте посмотрим на байт-код. Получение байт-кода дляif-then-else версия:

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
}
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.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded user1428716
3

switch на строки может быть быстрее по той же причине, почему поиск в наборе хеш-строк может быть быстрее, чем поиск в списке строк: вы можете выполнить поиск вO(1) а не вO(N), гдеN это количество строк.

Напомним, чтоswitch более эффективен, чем цепьif-then-else операторы, потому что это вычисляемый переход: смещение в коде вычисляется на основе значения, а затем выполняется переход к этому смещению. Java может использовать похожую хитрость для строк, используя механизм, аналогичный тому, который используется в хэш-картах и хэш-наборах

Похожие вопросы