哪些是java中最有效的?

时间:2012-04-27 10:47:14

标签: java performance conditional-statements

  

可能重复:
  Java: If vs. Switch

对于在编程中观察到的所有条件语句,最优选的是哪些块:

  1. 三元运营商
  2. else-if block
  3. switch block
  4. 提前致谢!

6 个答案:

答案 0 :(得分:5)

当然,您可以通过不同方式实施比较。

我是这样做的:

常见块:

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

然而,当您有多个案例时,开关的优势就会发挥作用 - 而不仅仅是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    

benchmark plot (Benchmark plot)

这表明,他们确实没有太大的区别,并且即使在加热VM之后,对于5 M的情况,缓存效果仍然会产生影响。

在实际情况下,你很少有百万次调用,几乎没有任何事情发生。但是如果发生了什么事情,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))
  }
}

更新

这是BenchCoat source

答案 1 :(得分:1)

三元运算符是最有效的,因为它不需要在其他if-if块的汇编中使用“goto”。我认为切换案例并不比else-if块更有效,假设你在else-if块中所做的只是将一个值与另一个值进行比较(因为基本上所有的开关都是最终的)。

但是,您应该考虑另一个因素:清晰度。更重要的是选择最有效的用法是编写清晰简洁的代码。为此,我建议使用else-if或切换块而不是三元运算符,因为你开始越过眼睛寻找返回的值,否则就会返回。

答案 2 :(得分:1)

如果使用现代编译器,则没有太大区别。在编译器优化代码之后,本机代码应该几乎相同。

答案 3 :(得分:0)

三元运算符只是编写if(某事物){yay} else {boo}的简写形式,执行更简单的赋值。三元运算符将扩展为if else结构,字节码没有区别。

答案 4 :(得分:0)

我做了以下测试:

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在转换它并运行insructions时是否会改变)

如果它说的是相同的逻辑,那么当我们谈论两个以上的条件时,Switch更多的是性能。

答案 5 :(得分:0)

这取决于JVM的实现以及版本,一般来说,如果声明是最快的,你不能说。

例如生成的字节码对于所有语句也可以是相同的。