10

I've had no real luck getting a concise answer for this comparison by using Google and rather than do my own time consuming evaluations, I thought I would ask first.

I'm fairly sure that a switch statement using Enums would perform faster than an if-then-else statement, though whether or not it is a noticable difference is another question.

Could someone shed some light on this for me?


Thanks for the quick responses guys, I will keep this in mind for future projects.

Carl Manaster
  • 39,912
  • 17
  • 102
  • 155
FizzBuzz
  • 558
  • 2
  • 13
  • 29
  • 3
    I highly doubt the performance difference will be anything more than micro optimization. I would go for switch stmt if it provides more readable and maintainable code in your case. – CoolBeans Feb 07 '11 at 15:21
  • I'm curious, what makes you say "I'm fairly sure that a switch statement using Enums would perform faster than an if-then-else statement"? – Pops Feb 07 '11 at 15:21
  • @Lord Torgamus - In a switch statement, each case is either true or false, in an if-then-else statement, each if could have multiple boolean values, i.e. this && that, or this || that, etc. And I just figure, evaluating more than one would take a bit more time. – FizzBuzz Feb 07 '11 at 15:25
  • I'm curious if you can get any measurable difference. For such microbenchmarking, I'd recommend http://code.google.com/p/caliper/ as it's very easy to use and designed by the Guava guys. I case you measure it, let's know the results. – maaartinus Feb 07 '11 at 15:40
  • 2
    It's not really about performance, imho - which of the two reads easier, is easier to maintain, is less bug-prone? Those should be more important motivations for choosing one over another than performance. I'm pretty sure you've already guessed that performance differences would be minimal / marginal at best. – cthulhu Feb 07 '11 at 15:45
  • Side note: consider replacing conditionals with polymorphism (Java enums even support abstract methods): http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html – Puce Feb 07 '11 at 16:06

6 Answers6

8

Yeap, it does, because in general term a switch statement works faster than if/else chain.

Although bytecode generated is not always definitive source for performance comparisons you can examine it to have a better idea.

For instance this code:

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(){}
}

Generates the following:

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

}

Which seems to be pretty fast in both cases.

So, pick the one that is easier to maintain.

OscarRyz
  • 196,001
  • 113
  • 385
  • 569
  • although switchs are typically faster, an example of when a switch is not so good is when the case statements are sparse and/or not in order, then it can loose it's advantages... but as always with any micro optimisation - timing tests is the only true answer :-) – SteelBytes Feb 07 '11 at 15:30
  • Three enum values is not going to make a difference. Try with 100 and you'll see one table lookup vs. 100 comparisons. – OrangeDog Feb 07 '11 at 15:41
  • @Orange And invoke a different method in each one, of course. – OscarRyz Feb 07 '11 at 15:59
7

Just stick with the most readable and clear to understand code you can come up with, I'm sure you lost all the time gained in the performance optimization while looking for this answer already. Micro-optimizations like this rarely are worth it and can easily result in code that's more complex than needed.

Mikko Wilkman
  • 1,495
  • 10
  • 8
1

I don't know about faster, I'd guess they are both blazingly fast.

My consideration is that switch with enums is a lot more readable than a multi-if/else block

But beware of missing break statements!!

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
1

Yes, a switch statement will pretty much always execute faster than the equivalent block of if / else statements because the compiler can perform more optimisations (typically a switch block becomes compiled down to a branch table which is pretty much impossible to do with a block of conditionals.)

I'd say they're also both more readable and more maintainable (with the exception of using fall-through cases which I'd advise against!)

As to whether it's noticeably faster, it depends what you define as noticeable. Chances are unless you're after something really specific you won't notice it at all, but I'd still do things this way because of the readability advantage more than anything else (treat the speed advantage as a bonus!)

Michael Berry
  • 70,193
  • 21
  • 157
  • 216
  • "(typically a switch block becomes compiled down to a branch table which is pretty much impossible to do with a block of conditionals.)" - but if the compiler is smart enough to see that it's just a list of variables compared with (numerical) constants (which is what enums are, deep inside), wouldn't it be able to optimize it just as if it were a switch/case? – cthulhu Feb 07 '11 at 15:47
  • @Cthulhu - I should've said it's impossible to do with the general case of a block of conditionals. Yes, in the instance you describe it theoretically would be, though I'm not sure the compiler actually does this analysis (IMO there's better optimizations worth concentrating on than this one anyway.) – Michael Berry Feb 07 '11 at 17:09
1

My answer to this is the same as always to question is language construct X generally faster than language construct Y: There is no general answer!

There may be only specific answer for certain implementations of a language, e.g. Oralce's (formally Sun's) Hotspot-compiler based JVM or for an IBM JDK on plattform Z or for an OpenJDK on Linux, or...

So, the only way to give a meaningfull answer to your question is to do a proper benchmark. Beware of micro benchmarks, they are more often wrong than right, see e.g. How not to write a micro benchmark. If you still want to find about use this question framework described here.

Therfore, I would advise to select language feature by their applicability and readibility in your context.

jmg
  • 7,308
  • 1
  • 18
  • 22
0

In theory a switch statement can be optimised as a single calculated jump, whereas if-then-else chains have to remain as individual comparisons. I don't know whether Java actually performs this optimisation though.

Regardless, switches are better than if-then-else chains in terms of readability and maintainability, so use them anyway if possible.

OrangeDog
  • 36,653
  • 12
  • 122
  • 207
  • From memory it does perform this calculated jump (it can easily do so because it restricts the types that can be used in a switch to primitives, enums and (in Java 7 and beyond) strings. – Michael Berry Feb 07 '11 at 15:34
  • @berry120 - I was thinking of the optimal optimisation (pad the cases with nops then jump forward `enum.ordinal() * sizeOfCase`). – OrangeDog Feb 07 '11 at 15:51