为什么switch语句比Java 7中的String更快?

Java 7中string对象可以在switch语句的表达式中。 有人可以从官方文档中解释以下声明吗?

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

Java代码

有两个版本的类,例如

使用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."":()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."":()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方法来比较字符串,直到找到它为止。

  • 在第二个版本中获取字符串的第一个hashCode 。 然后将其与每种case的值hashCode进行比较。 请参阅lookupswitch 。 如果重复这些值中的任何一个,则恰好运行该case的代码。 否则,调用绑定的case的equals方法。 这比以前更快地调用equals方法要快得多。

switch字符串可能会更快,原因与字符串哈希集中的查找可能比字符串列表中的查找更快的原因相同:您可以在O(1)而不是O(N)进行查找,其中N是字符串的数量。

回想一下, switchif-then-else语句链更有效,因为它是一个计算的跳转:代码中的偏移量是根据值计算的,然后执行跳转到该偏移量。 Java可以使用类似于哈希映射和散列集中使用的机制在字符串上引入类似的技巧。

它的效率更高:

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

通讯员:

 if (yourString.equals("text1")) { // your code } else if (yourString.equals("text2")) { // etc. } 

我想这意味着什么,或者我理解的是,使用字符串从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 }