可能重复:
Java:If vs. Switch
对于在编程中观察到的所有条件语句,这些块中的哪一个是最优选的:
- 三元运算符
- else-if 块
- 开关块
提前致谢!
当然,您可以通过不同的方式进行比较。
我是这样做的:
常见块:
int a = 42;
int k = 17;
如果:
if (a == 42)
k+=4;
else k+=5;
案子:
switch (a) {
case 42: k+=4; break;
default: k+=5; break;
}
三元:
k += (a == 42) ? 4 : 5;
它们不会编译为相同的字节码:
l *Tern*.class
-rw-r--r-- 1 stefan stefan 704 2012-04-27 14:26 CaseIfTern.class
-rw-r--r-- 1 stefan stefan 691 2012-04-27 14:26 IfTernCase.class
-rw-r--r-- 1 stefan stefan 728 2012-04-27 14:26 TernIfCase.class
但是,当您有多个案例时,switch 的优势就会发挥作用 - 而不仅仅是 2 个。
如果和三元级联超过2个案例。
但它们在惯用语/语义上有所不同。三元运算符返回一些东西,但不返回 if 或 switch。
所以还不清楚你必须比较什么。
但我做了一个基准测试,结果如下:
0 if tern case
1 3.103 0.244 0.118
2 0.306 0.276 0.309
3 0.382 0.329 0.328
4 0.464 0.435 0.458
5 5.045 1.519 1.248
6 4.57 3.088 2.915
7 4.036 2.977 3.015
8 3.197 3.834 3.893
9 4.631 4.523 5.488
10 6.445 3.891 3.09
这表明,它们确实没有太大的区别,而且缓存效果在 5M 的情况下仍然有影响,即使在加热 VM 之后也是如此。
在实际情况下,您很少有数百万次调用几乎没有任何反应。但是如果发生了什么事,if/case/ternary 的时间很快就会变得无关紧要。
这是我测试的代码:
public class CaseTernIf
{
public static int aORbIf (int a) {
if (a == 2)
return 4;
else return 5;
}
public static int aORbTern (int a) {
return (a == 2) ? 4 : 5;
}
public static int aORbCase (int a) {
switch (a) {
case 2: return 4;
default: return 5;
}
}
}
这是测试代码(Scala):
object IfCaseTernBench extends Benchcoat [List[Int], Seq[Int]] {
type I=List[Int]
type O=Seq[Int]
val name = "CaseTern"
/** We return a List of random Ints numbers here. */
def iGenerator (n: Int) : I = (for (x <- 1 to n) yield math.abs (random.nextInt (3))).toList
def takePart (li: I, n: Int) : I = li.take (n)
/* Each algorithm is called by a mapping to a static method. */
def ifTest (i: I) : O = i.map (CaseTernIf.aORbIf)
def caseTest (i: I) : O = i.map (CaseTernIf.aORbCase)
def ternTest (i: I) : O = i.map (CaseTernIf.aORbTern)
// Map of Test names -> methods to test
val list2bench: List [(String, I => O)] = List (
"if test" -> ifTest _
, "case test" -> caseTest _
, "tern test" -> ternTest _
)
def test = {
list2bench.foreach (algo => println (algo._2))
}
}
三元运算符是最有效的,因为它在 else-if 块需要的程序集中不需要“goto”。我认为 switch case 并不比 else-if 块更有效,假设你在 else-if 块中所做的只是将一个值与另一个值进行比较(因为基本上这就是 switch 最终所做的一切)。
但是,您应该考虑另一个考虑因素:清晰度。更重要的是选择最有效的用法是编写清晰简洁的代码。为此,我建议使用 else-if 或 switch 块而不是三元运算符,因为您开始交叉眼睛寻找否则返回的值。
如果您使用的是现代编译器,则没有太大区别。编译器优化代码后,原生代码应该差不多了。
这取决于 JVM 的实现以及版本,一般来说,您不能说语句是否最快。
例如,所有语句生成的字节码也可能相同。
我做了以下测试:
public class IfElseSwichTernary {
public static int aORbIf(int a) {
int x = 0;
if (a == 2) {
x = 4;
} else if (a == 3) {
x = 5;
} else if (a == 4) {
x = 6;
} else {
x = 7;
}
return x;
}
public static int aORbTern(int a) {
int x = 0;
x = (a == 2) ? 4 : ((a == 3) ? 5 : ((a == 4) ? 6 : 7));
return x;
}
public static int aORbCase(int a) {
int x = 0;
switch (a) {
case 2:
x = 4;
break;
case 3:
x = 5;
break;
case 4:
x = 6;
break;
default:
x = 7;
}
return x;
}
}
我用java反编译器反编译得到以下代码:
公共类 IfElseSwichTernary {
public static int aORbIf(int a) {
int x = 0;
if (a == 2) {
x = 4;
} else if (a == 3) {
x = 5;
} else if (a == 4) {
x = 6;
} else {
x = 7;
}
return x;
}
public static int aORbTern(int a) {
int x = 0;
x = (a == 2) ? 4 : ((a == 3) ? 5 : ((a == 4) ? 6 : 7));
return x;
}
public static int aORbCase(int a) {
int x = 0;
switch (a) {
case 2:
x = 4;
break;
case 3:
x = 5;
break;
case 4:
x = 6;
break;
default:
x = 7;
}
return x;
}
}
这意味着编译器不会改变任何东西(我不知道JVM在转换和运行指令时是否会改变)
当我们谈论两个以上的条件时,如果它以与 Switch 相同的逻辑表示,则更符合性能。
三元运算符只是 if (something) { yay } else { boo } 的一种简写形式,执行起来更简单。三元运算符将扩展为 if else 构造,字节码没有区别。