为什么在 Java 7 中,对于 String 的 switch 语句比 if else 更快?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10836055/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is the switch statement faster than if else for String in Java 7?
提问by user1428716
In Java 7a string
object can be in the expression of a switch
statement. Can someone explain the below statement from official documentation?
在Java 7 中,string
对象可以在switch
语句的表达式中。有人可以从官方文档中解释以下声明吗?
The Java compiler generates generally more efficient bytecode from switch statements that use String objectsthan from chained if-then-else statements.
Java 编译器从使用String 对象的switch 语句生成的字节码通常比从链接的 if-then-else 语句生成的字节码更有效。
回答by Paul Vargas
Java Code
Java代码
Having two versions of a class, e.g.
有两个版本的类,例如
With if-then-else
:
与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)) {
}
}
}
With switch
:
与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
字节码
Let's take a look at the bytecode. Getting the bytecode for if-then-else
version:
我们来看看字节码。获取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
}
Getting the bytecode for switch
version:
获取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
eachcase
. See thelookupswitch
. If any of these values ??is repeated just happens to run the code for thecase
. Otherwise, call theequals
method of the cases tied. This is much faster than ever call theequals
method only.
在第一个版本中,通过
equals
为每个条件调用方法来比较字符串,直到找到为止。在第二个版本中首先获得
hashCode
字符串。然后将其与值进行比较??hashCode
每个case
. 见lookupswitch
。如果这些值中的任何一个被重复,则恰好运行case
. 否则,调用equals
绑定的情况下的方法。这比equals
仅调用方法要快得多。
回答by dasblinkenlight
switch
on strings can be faster for the same reason why a lookup in a hash set of strings may be faster than a lookup in a list of strings: you can do a lookup in O(1)
rather than in O(N)
, where N
is the number of strings.
switch
在字符串中查找可能比在字符串列表中查找更快的原因相同:您可以在 inO(1)
而不是 in 中进行查找O(N)
,其中N
是字符串的数量。
Recall that switch
is more efficient than a chain of if-then-else
statements because it is a calculated jump: an offset in code is calculated based on the value, and then the jump to that offset is executed. Java can pull a similar trick on strings using the mechanism similar to that employed in hash maps and hash sets.
回想一下,这switch
比if-then-else
语句链更有效,因为它是计算跳转:代码中的偏移量是根据值计算的,然后执行到该偏移量的跳转。Java 可以使用类似于散列映射和散列集合中使用的机制在字符串上使用类似的技巧。
回答by javatutorial
It's more efficient something like:
它更有效,例如:
switch(yourString) {
case "text1":
// your code
break;
case "text2":
// etc.
}
than the correspondent:
比记者:
if (yourString.equals("text1")) {
// your code
} else if (yourString.equals("text2")) {
// etc.
}
回答by tagtraeumer
i guess what it means, or what i understand is that the bytecode (when you compile your java class) that created from an switch statement using string is faster and more efficient than the bytecode that is created from an if-else statement using string. both can do the same job, bit switch is apparently more efficient.
我猜这意味着什么,或者我理解的是,从使用字符串的 switch 语句创建的字节码(当您编译 java 类时)比使用字符串从 if-else 语句创建的字节码更快、更有效。两者都可以做同样的工作,位切换显然更有效。
switch (str) {
case "A":
// do something
break;
case "B":
// do something
break;
default:
//do something
break;
}
is better than
比
if(str.equals("A")) {
//do something
} else if(str-equals("B")) {
//do something
} else {
//do something
}