2

Possible Duplicate:
Java: If vs. Switch

For all the conditional statements that are observed in programming, which of these blocks is the most preferred:

  1. Ternary operator
  2. else-if block
  3. switch block

Thanks in advance!

Community
  • 1
  • 1
Anurag Ramdasan
  • 4,189
  • 4
  • 31
  • 53

6 Answers6

5

Of course you may implement the comparison in different ways.

I did it this way:

common block:

int a = 42;
int k = 17;

if:

if (a == 42) 
    k+=4;
else    k+=5;

case:

switch (a) {
    case 42: k+=4; break;
    default: k+=5; break;
}

Ternary:

k += (a == 42) ? 4 : 5; 

They don't compile to the same bytecode:

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

However, advantages of switch come into play when you have multiple cases - not just 2.

If and ternary get cascading for more than 2 cases.

But they differ idiomatically/semantically. The Ternary operator returns something, but not the if or the switch.

So it isn't that clear what you have to compare.

But I made a benchmark with following result:

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)

Which shows, that they really don't make much difference, and that caching effects have still, for 5 M cases, an influence, even after heating up the VM.

In real circumstances, you rarely have million invocations where nearly nothing happens. But if something happens, the time for if/case/ternary becomes soon irrelevant.

Here is the code I tested:

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; 
        }
    }
}

Here is the Testing code (which is 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))
  }
}

updated:

And here is the BenchCoat source

user unknown
  • 35,537
  • 11
  • 75
  • 121
  • 1
    so all the claims of it being compiled to same bytecode not true? – Anurag Ramdasan Apr 27 '12 at 13:11
  • 1
    @AnuragRamdasan: I think so. Since the code size differs. But maybe another implementation of what to compare exactly, or a different compiler, or maybe what the HotSpotCompiler finally does to the code will change the picture. – user unknown Apr 27 '12 at 13:29
  • Your table doesn't match your graph. – Neil Apr 27 '12 at 15:19
  • 2
    @Neil: Yes, thanks, I updated the table. I made a second run, after I made a more-or-less cosmetic code change, just to be sure, that the results don't change significantly. After updating the graph, I forgot to update the table. Now done. – user unknown Apr 27 '12 at 15:24
  • @userunknown, okay. :) Just pointing it out, you know fyi. I think you mixed case with tern on the graph also. – Neil Apr 27 '12 at 15:59
  • 2
    @Neil: Yes, but that shouldn't have happened. I corrected it manually, but I have to investigate the source of this error. – user unknown Apr 27 '12 at 23:19
  • 1
    I have a quick question. How exactly do you benchmark? I've never done it, and I assume I will need it as soon as I finish up my app prototype. Just a link would be great. I really appreciate it! – Andy Jun 10 '12 at 03:31
  • 1
    Doesn't the link at the bottom work for you, or what do you mean with `exactly`? It's a quick question, but not a quick answer. There are entire books written on it. – user unknown Jun 10 '12 at 03:58
1

Ternary operator is most efficient simply because it doesn't require "goto"'s in the assembly where else-if blocks do. I think switch cases are no more efficient than else-if blocks, assuming all you're doing in the else-if blocks is comparing one value to another (since essentially that's all switch is doing ultimately).

However, you should factor in another consideration: clarity. More important picking the usage which is most efficient is writing clear and concise code. For this, I would recommend else-if or switch blocks rather than ternary operators since you begin to cross eyes looking for the value that gets returned otherwise.

Neil
  • 5,762
  • 24
  • 36
  • 1
    He is asking in the terms of performence only. so this doesn't answer the question – GingerHead Apr 27 '12 at 10:55
  • 1
    Have you checked this by looking at byte code generated by a ternary? – Don Roby Apr 27 '12 at 10:55
  • @JohnDoe, I answered his question and added more pertinent information as well. – Neil Apr 27 '12 at 10:56
  • Check [this thread](http://www.coderanch.com/t/391402/java/java/Ternary-operator-if-condn) which actually tests this. – Neil Apr 27 '12 at 10:57
  • 1
    there is no goto in assembly when you don't use goto in the above condtional block arrangers case – GingerHead Apr 27 '12 at 10:59
  • There a reason why I was voted down? I've offered proof of my claims. Anyone care to justify their downvote? – Neil Apr 27 '12 at 12:34
  • [Minus One] For not being clear enough and having contradictions in so many ways off with the accepted answer. –  May 13 '15 at 14:33
1

There isn't much difference if you are using a modern compiler. After compiler optimizes the code, native code should be almost the same.

James Gan
  • 6,988
  • 4
  • 28
  • 36
0

The ternary operator is just a shorthand form of writing an if (something) { yay } else { boo }, with an easier assignment performed. The ternary operator will expand to an if else construct, there is no difference in bytecode.

rapadura
  • 5,242
  • 7
  • 39
  • 57
0

I did the following test:

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;
    }
}

And I decompied with a java decompiler and got the following code:

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;
}

}

Which means that the compiler doesn't change anything (I don't know if the JVM will change when converting it and running the insructions)

If it says in the same logic than Switch is more to the perfomace when we are talking more than two conditions.

GingerHead
  • 8,130
  • 15
  • 59
  • 93
0

It depends on the implementation of the JVM and also the version, you can't say in general, if a statement is the fastest.

for example the bytecode generated could also be the same for all statements.

Davide Consonni
  • 2,094
  • 26
  • 27