Switch statement vs Ifs in Java

Herbert Schildt in "The Complete Reference" - Chapter 5:

A switch statement is usually more efficient than a set of nested ifs.

When the compiler compiles a switch statement , it inspects each of the case constants and creates a "Jump Table" that it will use for selecting the path of execution depending on the value of the expression. Therefore, if you need to select among a large group of values, a switch statement will run much faster than the equivalent logic coded using a sequence of if-elses. The compiler can do this because it knows that the case constants are all the same type and simply must be compared for equality with the switch expression. The compiler has no such knowledge of a long list of if expressions.

  1. what does he mean by the term "JUMP TABLE"?

  2. Switch differs from if-statements in that, switch can test only for equality whereas if can evaluate any type of boolean expression. If a switch(expression) does not match any of the case constants, that means it goes inside the default case. Isn't it a case of unequality? That makes me think of having no such big difference between the switch and if.

  3. From an extract in the same book, he wrote:

    An if-then-else statement can test expressions based on ranges of values or conditions, whereas a switch statement tests expressions based only on a single integer, enumerated value, or String object.

    Doesn't that make if more powerful than switch?

  4. I have worked in different projects on Core Java, but never felt the need to make use of the switch statement, and also not seen other associates make use of it. Not even a single time. How come a much more powerful switch control statement fails to land itself ahead of if in terms of usability?

Upvotes: 0

Views: 3088

Answers (5)

Tim B
Tim B

Reputation: 41168

I use switch all the time, if you aren't using it you're doing Java wrong.

A jump table can be thought of like an array of locations in the code. For example imagine the following:

case 0:
   // do stuff
   break;
case 1:
   // do stuff 2
   break;
case 3:
   // do stuff 3
   break;

Then you have a jump table just containing

codeLocations[] = { do stuff, do stuff 2, do stuff 3 }.

Then to find the correct bit of code for case 1 Java just needs to goto codeLocations[1]. No actual integer comparisons are needed.

Obviously the actual implementation is rather more complicated than this as it needs to handle much more varied cases but it gives the idea.

Neither if nor switch are more powerful than each other. They are both tools. You're asking whether a hammer is more powerful than a screwdriver. Yes a hammer will knock more things into the wood, but a screwdriver will do a better job if you are working with screws :)

To expand on the "doing java wrong" thing:

Switch is a tool in the Java language, one that has been added for a reason.

You could apply the exact same question to for loops. Everything you can do with a for loop you can also do with a while loop (although it will likely involve writing quite a bit more code). Try it sometime.

This doesn't make while "more powerful" or even "more useful" than for. They are different tools with different strengths and weaknesses.

switch and if are the same as for and while. They do similar jobs and in a lot of places you could use either. However there are clear examples where one is preferable to the other.

If you are programming using a language while ignoring one of the fundamental tools in that languages toolkit then you are using that language wrong. This is not some obscure feature that hardly ever gets used, this is one of the primary flow control statements in the language.

If a carpenter only ever uses a hammer and never uses a screwdriver... they are doing it wrong. Equally if a programmer never uses a significant language feature...they are doing it wrong.

A proverb applies here "If the only tool you have is a hammer, everything looks like a nail".

Upvotes: 3

Margus
Margus

Reputation: 20038

In layman's terms difference is negligible.

Both have their pros and cons. In most cases you would never use switch - instead you would use hashmap with actions or some other construct that has better readability.

I would reccomend you read Efficient Java or https://code.google.com/p/guava-libraries/wiki/GuavaExplained

In c# you could write this like :

class MyClass
{
    static Dictionary<string, Func<MyClass, string, bool>> commands
        = new Dictionary<string, Func<MyClass, string, bool>>
    {
        { "Foo", (@this, x) => @this.Foo(x) },
        { "Bar", (@this, y) => @this.Bar(y) }
    };

    public bool Execute(string command, string value)
    {
        return commands[command](this, value);
    }

    public bool Foo(string x)
    {
        return x.Length > 3;
    }

    public bool Bar(string x)
    {
        return x == "";
    }
}

After that you could have

var item = new MyClass();
item.Execute("Foo","ooF");

Upvotes: 0

Simulant
Simulant

Reputation: 20102

1) The compiler creates a table with a row for every case statement, where the case condition is the key and the block of code is the value. When the switch statement is executed in your code, the block of the case can directly be accessed by the key of the case block. Where in nested if blocks you need to check and execute every condition before your will find the right one where your enter the conditional block of code.

Think of it like a hashtable (for switch case) compared to a linear linked list (for nested if statements) and compare the time to look up a specific value. The lookup time of a table is O(1) (just get it in one operation) where the lookup time in the linked list is O(n) (look at every item until you get the right one).

3) yes, an if statement can be used more flexible and express more, but in the case you want to switch between different codeblocks for a list of different values a switch block is executed faster and more readable.

4) you never need to use a switch because nested ifs can express the same, but in some cases it is more elegant. But because of the rare time it is good to use, programmers forget about it and don't use it even in the spots where it would fit better.

2) extract the difference out of the answers to the other points.

Upvotes: 5

E_net4
E_net4

Reputation: 29972

1) In a switch case, a jump table maps a position in the code segment to a particular case. For instance, considering this snippet:

int a;
// a is manipulated here
switch (a) {
    case 1: // address 0
        // ...
        break;
    case 2: // address 1
        // ...
        break;
    case 3: // address 2
        // ...
        break;
    default: // other cases
        // ...
        break;
}

There would be a jump table mapping a=1 to the effective code address marked by address 0, a=2 to address 1, and so on. This can become more apparent when observing the resulting bytecode. With this approach, the number of conditional jumps in the bytecode becomes much smaller than in the case of if-else statements.

2) It's true that if-else statements can test of unequality, but achieving the same behavior of a switch-case statement involves chaining if-else statements. Here is an equivalent version of the above in terms of behavior.

if (a==1) {
    // ...
} else if (a==2) {
    // ...
} else if (a==3) {
    // ...
} else {
  // for any other cases
}

It could be a matter of personal opinion at some point, but a switch-case statement is more readable in this particular case. But naturally, if-else statements are still indispensable, and you are expected to use the right tool for the job. If-else is more versatile than switch-case, but the latter may produce nicer code in some places. Hopefully, this answers the 3rd and 4th part of your question.

Upvotes: 2

phoog
phoog

Reputation: 43036

1: A jump table is a table of jump targets. A jump target is an address in the code that corresponds to the code belonging to a case in the switch. If your switch cases are, for a simple example, 0, 1, ... N, then the N + 1 targets would be at index 0, 1, ... N of the table, respectively. You just calculate the value you're switching on an then look up the target by indexing into the table, not by comparing N + 1 times. That's the efficiency.

2: default is a case of inequality, yes, but very limited, as you note. Its the case for "not equal to any other of the cases" but it can't be "less than a given value" or "greater than..."

3: Yes, if is more powerful. However, switch is more efficient, sometimes. Efficiency != power.

4: Power != efficiency. But, to answer the implied question: the more efficient switch statement is not used because your colleagues have not used it. You have to ask them why. Maybe it's a matter of taste, or of ignorance of the advantages of switch. The greater efficiency of a switch statement is almost always going to be unnoticeable, unless you are in a very performance-sensitive context, so people are generally unaware of it. If performance is not paramount, then readability is. In some cases a developer might consider a switch statement and decide that a series of if statements is easier to read and understand.

Upvotes: 2

Related Questions