我没有真正的幸运,通过使用谷歌获得这个比较的简明答案,而不是做我自己耗时的评估,我想我会先问。
我很确定使用Enums的switch语句比if-then-else语句执行得更快,不管它是否是一个明显的区别是另一个问题。
有人可以为我解释一下吗?
感谢快速反应人员,我将在未来的项目中牢记这一点。
答案 0 :(得分:8)
是的,确实如此,因为通常来说,switch语句比if / else链更快。
尽管生成的字节码并不总是性能比较的明确来源,但您可以检查它以获得更好的想法。
例如这段代码:
class A {
enum N { ONE, TWO, THREE }
void testSwitch( N e ) {
switch( e ) {
case ONE : x(); break;
case TWO : x(); break;
case THREE : x(); break;
}
}
void testIf( Enum e ) {
if( e == N.ONE ) { x(); }
else if( e == N.TWO ) { x(); }
else if( e == N.THREE ) { x(); }
}
void x(){}
}
生成以下内容:
Compiled from "A.java"
class A extends java.lang.Object{
A();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
void testSwitch(A$N);
Code:
0: getstatic #2; //Field A$1.$SwitchMap$A$N:[I
3: aload_1
4: invokevirtual #3; //Method A$N.ordinal:()I
7: iaload
8: tableswitch{ //1 to 3
1: 36;
2: 43;
3: 50;
default: 54 }
36: aload_0
37: invokevirtual #4; //Method x:()V
40: goto 54
43: aload_0
44: invokevirtual #4; //Method x:()V
47: goto 54
50: aload_0
51: invokevirtual #4; //Method x:()V
54: return
void testIf(java.lang.Enum);
Code:
0: aload_1
1: getstatic #5; //Field A$N.ONE:LA$N;
4: if_acmpne 14
7: aload_0
8: invokevirtual #4; //Method x:()V
11: goto 39
14: aload_1
15: getstatic #6; //Field A$N.TWO:LA$N;
18: if_acmpne 28
21: aload_0
22: invokevirtual #4; //Method x:()V
25: goto 39
28: aload_1
29: getstatic #7; //Field A$N.THREE:LA$N;
32: if_acmpne 39
35: aload_0
36: invokevirtual #4; //Method x:()V
39: return
void x();
Code:
0: return
}
在这两种情况下,这似乎相当快。
所以,选择一个更容易维护的。
答案 1 :(得分:7)
只要坚持用你能想到的最易读和最清晰的代码,我确信你已经失去了在性能优化中获得的所有时间,同时也在寻找这个答案。像这样的微优化很少值得,并且很容易导致代码比需要的更复杂。
答案 2 :(得分:1)
我不知道更快,我猜它们都非常快。
我的考虑是带有枚举的开关比多个if / else块
更具可读性但要注意缺少休息陈述!!
答案 3 :(得分:1)
是的,一个switch语句几乎总是比if / else语句的等效块执行得更快,因为编译器可以执行更多的优化(通常一个switch块被编译成一个分支表,这几乎是不可能的一系列条件。)
我会说他们也更具可读性和可维护性(除了使用我建议反对的堕落案例之外!)
至于它是否明显更快,它取决于你定义的明显。机会是除非你在完全具体的事情之后你根本不会注意到它,但是我仍然会这样做,因为可读性优势比什么都重要(把速度优势视为奖励!)
答案 4 :(得分:1)
我对此的回答与以往一样,问题是语言构造X通常比语言构造更快Y:没有一般答案!
对于某种语言的实现,可能只有特定的答案,例如: Oralce(正式的Sun)基于Hotspot编译器的JVM或者平台Z上的IBM JDK或Linux上的OpenJDK,或者......
因此,对您的问题给出有意义的答案的唯一方法是做一个适当的基准。谨防微观基准,他们往往错误而不是正确,例如, How not to write a micro benchmark。如果您仍想查找有关使用此问题的framework here。
因此,我建议根据您的适用性和可读性选择语言功能。
答案 5 :(得分:0)
理论上,switch语句可以优化为单个计算跳转,而if-then-else链必须保持为单独的比较。我不知道Java是否实际执行了此优化。
无论如何,在可读性和可维护性方面,交换机比if-then-else链更好,所以尽可能使用它们。