Javaドキュメンテーション は言う
Javaコンパイラーは、一般にチェーン化されたif-then-elseステートメントよりもStringオブジェクトを使用するswitchステートメントからより効率的なバイトコードを生成します。
知る限り、スイッチ内の文字列は、大文字と小文字を区別する方法で内部的に.equals()
を使用します。そのため、このコンテキストでは効率とはどういう意味ですか。より高速なコンパイル?バイトコードが少ない?よりよい性能?
Switchステートメントの使用は、同等よりも高速です(ただし、文字列が数個以上ある場合にのみ顕著です)。最初にhashCode
がオンになっている文字列のswitch
を使用して、一致する可能性のある文字列のサブセットを決定します。ケースラベルの複数の文字列に同じhashCodeがある場合、JVMはequals
の順次呼び出しを実行し、hashCodeであるケースラベルに1つの文字列しかない場合でも、JVMはequals
を呼び出して文字列がcaseラベルは、switch式のラベルと実際に同じです。
Stringオブジェクトのスイッチの実行時パフォーマンスは、HashMap
でのルックアップに匹敵します。
次のコード:
public static void main(String[] args) {
String s = "Bar";
switch (s) {
case "Foo":
System.out.println("Foo match");
break;
case "Bar":
System.out.println("Bar match");
break;
}
}
次のコードのように内部的にコンパイルされ、実行されます。
(文字通りではありませんが、両方のコードを逆コンパイルすると、まったく同じアクションのシーケンスが発生することがわかります)
final static int FOO_HASHCODE = 70822; // "Foo".hashCode();
final static int BAR_HASHCODE = 66547; // "Bar".hashCode();
public static void main(String[] args) {
String s = "Bar";
switch (s.hashCode()) {
case FOO_HASHCODE:
if (s.equals("Foo"))
System.out.println("Foo match");
break;
case BAR_HASHCODE:
if (s.equals("Bar"))
System.out.println("Bar match");
break;
}
}
generalでは、switch文は(おおざっぱに言えば)O(1)
であるため優れていますが、_if-else
_のチェーンはO(n)
です
n
条件があると、チェーンの_if-else
_ステートメントを使用して、最大n
の比較が発生する可能性があります。
Switchステートメントは、適切な条件(マップなど)またはデフォルトのケースに直接「ジャンプ」して、O(1)
にすることができます。
これは、ドキュメントの例から生成されたバイトコードフラグメントです。
INVOKEVIRTUAL Java/lang/String.hashCode ()I
LOOKUPSWITCH
-2049557543: L2
-1984635600: L3
-1807319568: L4
lOOKUPSWITCHを使用すると、if-elseロジックに比べてパフォーマンスが向上します。