switch语句中的String如何比相应的if-else语句更有效?

Ani*_*kur 60 java string if-statement switch-statement

Java文档

Java编译器通常使用String对象生成比使用链式if-then-else语句更高效的字节码.

AFAIK even String in switch在.equals()内部以区分大小写的方式使用.那么它们在这种背景下的效率是多少.编译速度更快?字节码少?更好的性能?

Erw*_*idt 74

使用switch语句比equals更快(但只有在不止一些字符串时才会显着)因为它首先使用on hashCode的字符串switch来确定可能匹配的字符串子集.如果case标签中的多个字符串具有相同的hashCode,则JVM将执行顺序调用equals,即使在case标签中只有一个字符串表示hashCode,JVM需要调用equals以确认该字符串是否为case label实际上等于switch表达式中的label.

String对象上的开关的运行时性能与a中的查找相当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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在内部编译并执行像这段代码:

(不是字面意思,但是如果你反编译两段代码,你就会看到完全相同的动作序列发生)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 他们也可以使用trie实现 (4认同)
  • 有关内部编译的更多详细信息,请访问:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.10 (2认同)

Tyl*_*ler 20

一般,开关语句是更好,因为它们是(严格意义上)O(1),而链if-elseO(n)

n可能导致高达条件下n使用链式比较if-else报表.

switch语句可以直接"跳转"到适当的条件(如地图)或默认情况下制作它O(1).

  • 根据@Erwin Bolwidt提供的解释,这是有道理的. (5认同)

Evg*_*eev 7

这是从docs中的示例生成的字节码片段:

 INVOKEVIRTUAL java/lang/String.hashCode ()I
    LOOKUPSWITCH
      -2049557543: L2
      -1984635600: L3
      -1807319568: L4
Run Code Online (Sandbox Code Playgroud)

与if-else逻辑相比,使用LOOKUPSWITCH具有更好的性能

  • LOOKUPSWITCH是一直存在的字节码指令.当它接通的整数值间隔很大时,它用来代替TABLESWITCH.正如您在程序集中看到的那样,它不会打开字符串本身,而是打开字符串的hashCode.你需要在L2,L3或L4显示字节码:你会看到需要调用String.equals来验证字符串是否真的相同. (5认同)
  • @ErwinBolwidt但有趣的是,TABLESWITCH并不一定是听起来像:默认设置,在17种情况下,它被转换为汇编中的cmp/je系列(即if/goto).在18个或更多的情况下,它也成为装配级别的真正的工作台开关. (2认同)
  • 有趣的。还注意到(至少)Eclipse 编译器不会发出 TABLESWITCH,即使您打开具有连续哈希码(“A”、“B”、“C”等)的字符串。 (2认同)