Java文档说
The Java compiler generates generally more efficient bytecode from switch statements that use String objects than from chained if-then-else statements.
AFAIK even String in switch在内部使用.equals()以区分大小写的方式。 那么它们在这种背景下的效率是多少。 编译速度更快? 字节码少? 更好的性能?
有用的链接:blackwasp.co.uk/SpeedTestIfElseSwitch.aspx
顺便说一下,向所有人道歉; 我昨晚睡着了,显然是在写一个基于哈希的调度表的连接。 是的,这非常有意义,不仅适用于非整数值,还适用于宽间距稀疏值。"注意:为了避免损害声誉,请在将手指放入装备前进行大脑活动。"
使用switch语句比equals更快(但只有当不止一些字符串时才会显着)因为它首先使用switch的字符串的hashCode来确定可能匹配的字符串子集。如果case标签中的多个字符串具有相同的hashCode,则JVM将执行对equals的顺序调用,即使case标签中只有一个字符串表示hashCode,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;
}
}
他们也可以使用trie实现
有关内部编译的更多详细信息,请访问:docs.oracle.com/javase/specs/jvms/se7/html/
通常,switch语句更好,因为它们(松散地说)是O(1),而if-else的链是O(n)
具有n条件可能导致使用链式if-else语句进行最多n次比较。
switch语句可以直接"跳转"到适当的条件(如地图)或默认情况下,使其成为O(1)。
根据@Erwin Bolwidt提供的解释,这是有道理的。
这是从docs中的示例生成的字节码片段:
INVOKEVIRTUAL java/lang/String.hashCode ()I
LOOKUPSWITCH
-2049557543: L2
-1984635600: L3
-1807319568: L4
与if-else逻辑相比,使用LOOKUPSWITCH具有更好的性能
LOOKUPSWITCH是一直存在的字节码指令。当它接通的整数值间隔很大时,它用来代替TABLESWITCH。正如您在程序集中看到的那样,它不会打开字符串本身,而是打开字符串的hashCode。您还需要在L2,L3或L4显示字节码:在那里您将看到需要调用String.equals来验证字符串是否真的相同。
@ErwinBolwidt但有趣的是,TABLESWITCH并不一定是听起来像:默认设置,在17种情况下,它被转换为汇编中的cmp / je系列(即if / goto)。在18个或更多的情况下,它也成为装配级别的真正的工作台开关。
有趣。还注意到(至少)Eclipse编译器即使在您使用连续的hashCodes("A","B","C"等)切换字符串时也不会发出TABLESWITCH。