18

Java 7 では、ステートメントの式にstringオブジェクトを含めることができます。誰かが公式文書switchから以下の声明を説明できますか?

一般に、Java コンパイラは、連結された if-then-else ステートメントからよりも、String オブジェクトを使用する switch ステートメントからより効率的なバイトコードを生成します。

4

4 に答える 4

40

Javaコード

クラスの2つのバージョンがある、例えば

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

バイトコード

バイトコードを見てみましょう。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
}

結論

  • equals最初のバージョンでは、条件が見つかるまで、各条件のメソッドを呼び出して文字列を比較します。

  • 2番目のバージョンではhashCode、文字列の最初に取得されます。次に、これは値<code>hashCodeeachと比較されますcase。を参照してくださいlookupswitch。これらの値のいずれかが繰り返される場合は、たまたまのコードを実行しますcaseequalsそれ以外の場合は、関連付けられているケースのメソッドを呼び出します。これは、equalsメソッドのみを呼び出すよりもはるかに高速です。

于 2012-05-31T15:38:03.130 に答える
3

switch文字列のハッシュセットでのルックアップが文字列のリストでのルックアップよりも高速であるのと同じ理由で、文字列でのルックアップは高速になる可能性があります。O(1)ではなくでルックアップを実行できます。O(N)ここNで、は文字列の数です。

switchこれは計算されたジャンプであるため、ステートメントのチェーンよりも効率的であることを思い出してくださいif-then-else。コード内のオフセットは値に基づいて計算され、そのオフセットへのジャンプが実行されます。Javaは、ハッシュマップやハッシュセットで採用されているメカニズムと同様のメカニズムを使用して、文字列に対して同様のトリックを引き出すことができます。

于 2012-05-31T15:02:20.097 に答える
2

次のような方が効率的です。

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

特派員より:

if (yourString.equals("text1")) {
     // your code
} else if (yourString.equals("text2")) {
     // etc.
}
于 2012-05-31T15:00:03.460 に答える
-1

それが何を意味するのか、または私が理解しているのは、文字列を使用してswitchステートメントから作成されたバイトコード(Javaクラスをコンパイルするとき)は、文字列を使用して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
}
于 2012-05-31T15:01:37.147 に答える