I have two sets of conditions. One has two possible values and the other has more (in this example I wrote 3 cases but there could be up to 8). Which code runs faster and is less error prompt (more accurate)?
code a)
if (letter.equals(a)) {
switch (number) {
case 1:
.........
case 2:
.........
case 3:
.........
}
} else if (letter.equals(b)) {
switch (number) {
case 1:
.........
case 2:
.........
case 3:
.........
}
}
code b)
switch (number) {
case 1:
if (letter.equals(a)) {
.........
} else if (letter.equals(b)) {
.........
}
case 2:
if (letter.equals(a)) {
.........
} else if (letter.equals(b)) {
.........
}
case 3:
if (letter.equals(a)) {
.........
} else if (letter.equals(b)) {
.........
}
}
Please tell me if you think there is a better option other than these two. (I could also create a parameter that gets both letter and number and create 6 cases using that.)
Thank you in advance!
Which code runs faster and is less error prompt (more accurate)?
Answer: In this specific case performance is not the issue. Because no matter how you are going to use this actual execution numbers are same. But you can improve the code readability and making it less errorprone.
Instead of worrying about performance, start with SOLID principle. Why don't you just break this big method into some smaller method which has a concrete responsibility. It will make code more beautiful and less error prone. For example:
Methods:
void processA(int number){
switch (number) {
case 1:
.........
case 2:
.........
case 3:
.........
}
}
void processB(int number){
switch (number) {
case 1:
.........
case 2:
.........
case 3:
.........
}
}
///
now from the main method you could simply call:
if (letter.equals(a)) {
// call the method which will process A
processA(number);
} else if (letter.equals(b)) {
// call the method which will process A
processB(number);
}
This is an example of a micro-optimisation that probably has no effect on your code, so 'which is faster' doesn't really matter here.
If you want to find out which of a particular combination of cases in your codebase then you probably want to use a benchmarking tool like JMH to figure out which is more appropriate for you. But unless this code is on the critical path it won't make a difference.
Code needs to be:
Correct
Readable
Performant
It's much better to focus on 1 & 2 than the last.
In this particular case, a switch-over-numbers is probably faster for the JVM under the covers, while switch-over-expressions will naturally involve more jumping around in the branches. I would therefore naively expect switch-over-int-followed-by-if will marginally edge out the other way around, but without proof this would be a hunch and not something to rely on. It's also quite likely that whatever benchmark is written there will be some kind of flaws, such that the JVM is automatically promoting the optimal test case combination to the first test, in which case it won't tell you what you think it is doing.
Ultimately, write it for readability/maintainability rather than performance, until you can prove this is on the hot loop, and then measure it explicitly.
There is another option:
switch (String.format("%1s%1d", letter, number) {
case "a1":
...
case "b1":
...
case "a2"
...
case "b2":
...
case "a3":
...
case "b3":
...
}
Better? Maybe, maybe not. But it is an alternative...
Related
I would like to do something like this:
int i = 0;
switch(difficulty) {
case 1: i++; break;
case 2: i--; break;
default: case 1;
}
Is something like this possible? I want to prevent duplicate code. I know that in this particular example there is little reason to do this, since the duplicated code would be small. The only thing I can come up with is something like this [using the fall through abilities of switch cases]:
switch(difficulty) {
case 2: i--; break;
default:
case 1: i++; break;
}
I would rather not do it like this, since it would make more sense to increase case numbers and have the default at the bottom.
But I wonder that if I would do this, would it mess up with the goto statements under the hood? In particular, will it not take longer to decide which goto statement to use since the numbers or out of order? Does the order matter in the switch statement? Imagine all cases have the same odds of being called, would it matter if you had them in random order instead of linear order?
[Edit: for my side question about efficiency I found this: Does the order matter of switch-statements, the short answer is no: Does switch case order affect speed?
How does Java's switch work under the hood?
This should suit your needs:
switch(difficulty) {
case 2: i--; break;
default: i++; break;
}
This is probably what you need/want, and is valid code
int i = 0;
switch (difficulty) {
default:
case 1: i++; break;
case 2: i--; break;
}
As far as I know, the order of the cases does not alter in any way the switch statement, either your parameter is fit for a case or it isn't, so it doesn't matter, in your case, which case you have first.
You can see the documentation as reference if you wish.
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
(moved from comment, since it seemed to be helpful)
Add a private method and call it from both case 1 and default, that way you won't have duplicated code.
No, in switch statement order doesn't matter at all.
Also the compiler always maintain a hash table for jumping to the switch statement. So ordering or increase of casing is not a matter at all. It's always a O(1) operation.
However, this will reduce the switching for your case:
switch(difficulty) {
case 2: i--; break;
default: i++; break;
}
I have a primitive question but I can't actually recall the answer.
What if I use Switch Cases instead of IF\ELSE IF. Will all cases get evaluated or break will break out of the whole switch cases and return the first satisfied condition only.
In other words, what if I want to check if someone has a car, bike and plane. And in my particular case someone has all of them would switch return all three as true or it will return the first case only and ignore the rest because of the break?
Sorry for inconvenience.
Thank you
From the Official Java Tutorials :
Each break statement terminates the enclosing switch statement.
In your particular case, if someone has a car, bike or a plane, you should construct more complex if\else statement.
But if you still prefer to use switch, you can do the following:
switch (possession)
{
case CAR:
case BIKE:
case PLANE:
doSomething();
break;
}
It will break out at the first matching. the best thing to do in your case is using logical operators in if statements.
if (hasCar && hasBike && hasPlane)
{
...
}
The break terminates the switch-statement.
Besides, switch evaluates a single variable, your case sounds a bit more complex to me.
certainly break will break the switch-case flow after encountering first break statementif no break is found then it will start the execution of all statement starting from first matching case,you can implement the logic inside case.and one thing more switch case is little bit faster than if-else
please see Why switch is faster than if
With switch the first case it finds a match runs and then all the following cases regardless of matching or not, provided you don't use break. By using break,only the actual match case runs and it is almost always only one. Therefore I do not regard in your problem using switch as a good approach, since you can handle it better with if-else.
Perhaps you would need to rewrite a new style of Data Structure to confirm this. The easyest way that I think is with a Boolean Array (bool[]);
Continuing with your example if you has the
Owner Class
, with
bool bike, bool car, bool motocycle... properties, witch you can write a
public bool[] ownArray()
function, that can be evaluated.
I hope this helps.
myEnum = 3;
...
switch (myEnum) {
case 1: System.out.println("This will not print"); break;
case 2: System.out.println("This will not print"); break;
case 3: System.out.println("This will print!"); //no break!
case 4: System.out.println("So will this, because there wasn't a break"); break;
case 5: System.out.println("But this won't, there was a break");
}
Switch-case in java could evaluate one case at a time. The moment it gets into one of the case, it would keep on executing the next statements (no matter, if those statement were part of other case ); until it hit a break;
In nutshell, A switch statement gives you the option to test for a range of values for your variables. They can be used instead of long, complex if … else if statements. The structure of the switch statement is this:
switch ( variable_to_test ) {
case value1: code_here1;
break;
case value2: code_here2;
case value3: code_here3;
break;
default:
values_not_caught_above;
}
In the above example if value2 is satifies, it will execute code_here2 and code_here3 as well (because there is no break statement)
Sadly, you can't test for a range of values after case, just the one value. So you can't do this:
case (user <= 18):
This question already has answers here:
Why do we need break after case statements?
(17 answers)
Closed 9 years ago.
I already searched in stackoverflow for reasons concerning the question, why switch does not break after having found a matching case.
For example, I have written some code which simulates a dice. For every throw, I count up for statistical reasons (one, ... = int).
switch (actualThrow) {
case (1): one++;
case (2): two++;
case (3): three++;
case (4): four++;
case (5): five++;
case (6): six++;
}
I DO know, that case(3)-case(6) will be checked, if my throw was a 3 (Why do we need break after case statements?) and it will be prevented by inserting break;, but I want to understand, why obviously the following cases seem to be checked, but execute, although the condition is not fulfilled.
Imagine this scenario:
switch(trafficLight.state) {
case GREEN:
car.drive();
break;
case YELLOW:
car.drive();
break;
case RED:
car.stop();
break;
}
Seems kinda wasteful since GREEN and YELLOW both do the same thing. Java lets us consolidate so that multiple conditions take the same action:
switch(trafficLight.state) {
case GREEN:
case YELLOW:
// Now both GREEN and YELLOW will use this code
car.drive();
break;
case RED:
car.stop();
break;
}
Less code, same effect. That's all. That's the simple case mind you, there are other ways to use this that are less obvious and more prone to abuse.
When parsing through a switch-case statement, each case is simply a label. If anything matches a case then it will just go through until it either finds a break or the end of the statement (a }).
It is similar to the Java opcode (assembly code essentially). You use labels to jump to. Besides that, they don't really serve a purpose in the code.
I'm using int[] arrays as a reference. I wondering if my use of case statements is sound or if it will cause errors down the line.
This is my code:
int switcheroo = intarray[0];
int foo = intarray[1];
boolean size = false;
boolean biggersize = false;
switch (switcheroo) {
case 0:
switch (foo) {
case 1:
doSomething(switcheroo); //change switcheroo somehow.
break;
case 2:
doSomethingElse(switcheroo); //change switcheroo differently.
break;
}
case 1:
size = true;
break;
case 2:
biggersize = true;
break;
default:
break;
}
Unless it's a coincidence, this is working to ripple the changes from the nested case statement into the other cases, as I want.
My questions are:
Will this nesting causes trouble further down the line?
Is the lack of a break; after a case bad practice?
Thanks.
Edit: The methods which change switcheroo in the middle of the switch statements were put there for responses to that. I will not be doing this is my program.
Nesting won't cause trouble down the line exactly, but it can be confusing to read. Adding comments and/or other documentation will really help future coders (and yourself in a week!) understand this by looking at it.
The lack of a break isn't a bad practice by itself, but it is something that -most- case statements have, so I would add a comment at the end like // no break, allow fall-through.
So both cases boil down to good documentation.
These points are perpendicular to the fact that I don't think this code does what you think it will do.
The case clause is not reevalauted every time you come across one - they're just points to jump to for the switch. So in your example, you will always end up in case 1 if you start at case 0 - you'll never end up at case 2 from case 0.
If I were to restructure this, here's what I would do. Instead of using int, I would use enum:
enum Foo { GOOD_FOO, BAD_FOO }
enum Switcharoo { BAR, BAZ, BAQ, ESCAPE }
enum Size { NONE, REGULAR, BIGGER }
Foo foo = ... // assigned somewhere
Switcharoo roo = ... // assigned somewhere
Size size = NONE;
// use a while loop to reevalulate roo with each pass
while(roo != Switcharoo.ESCAPE) {
switch(roo){
case BAR:
switch(foo) {
case GOOD_FOO: foo = doSomething(foo); break;
case BAD_FOO: foo = doSomethingElse(foo); break;
}
break;
case BAZ:
roo = Switcharoo.ESCAPE;
size = Size.REGULAR;
break;
case BAQ:
roo = Switcharoo.ESCAPE;
size = Size.BIGGER;
break;
}
}
RE: Is the lack of a break; after a case bad practice?
If you don't include a break after each case statement the flow will continue trough the next statements, so the code for more than one option will be executed.
From the Java Tutorial:
Another point of interest is the break statement. Each break statement
terminates the enclosing switch statement. Control flow continues with
the first statement following the switch block. The break statements
are necessary because without them, statements in switch blocks fall
through: All statements after the matching case label are executed in
sequence, regardless of the expression of subsequent case labels,
until a break statement is encountered.
Check http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html to learn more details about switch statements.
In case foo is neither 1 nor 2, is switcheroo supposed to continue to case 1? If yes, your code is correct. If not, you need to add a break before case 1
switch operator is a kind of conditional if operator. And a bunch of if operators may report that you need to involve object polymorphism in your code instead of making sequental if-switch operators.
Consider re-arranging your data to classes/objects and process them using polymorphism approach. It will make your code more reliable, more manageable and just more beautiful.
Im not sure if i understood your first question, can you give me some more information (concrete maybe)?
Concerning the second question, there's nothing wrong about not having a break statement after a case, as long as you know that the code will continue to execute till it finds a break statement.
well..It seems the only thing you lack here is readability. Do this type of nesting only if you are forces to do.
Is the lack of a break; after a case bad practice?
not bad rather it is a good practice to avoid unsual behaviour. Your code will continue executing to your last case in absensce of this Break.
Add break in your first outer case too.
I'd recommend avoiding nesting and fall-through in combination. At least personally, I tend to expect that every case ends with a break, so I'd use fallthrough only in cases where it's very easy to spot, and leads to clearer code than an if..else, such as:
switch (foo) {
case 0:
case 1:
doSomething();
break;
case 2:
doSomethingElse();
break;
default:
break;
}
That is, with either empty or very simple (one statement) case bodies. In your case, refactoring the body of the first case into a method would probably work:
void changeSwitcheroo(int foo, int switcheroo) {
switch (foo) {
case 1:
doSomething(switcheroo); //change switcheroo somehow.
break;
case 2:
doSomethingElse(switcheroo); //change switcheroo differently.
break;
}
}
// ...
int switcheroo = intarray[0];
int foo = intarray[1];
switch (switcheroo) {
case 0:
changeSwitcheroo(foo, switcheroo);
case 1:
size = true;
break;
case 2:
biggersize = true;
break;
default:
break;
}
(This is mostly arguing readability and style. The meaning of the switch will still be "if switcheroo is 1, jump into the middle of case 0.)
If there are only 2 alternatives, prefer an if/else. Fewer lines of code and no break issues.
Will this nesting causes trouble further down the line?
A problem is that such switch nesting is hard to read: I had to look at the code twice before I noticed that you were using a nested switch. This can be a maintenance issue, but that isn't a reason not to use a nested switch, just use this sparingly, adjust your indentation to clarify what's going on, and comment on the usage.
Is the lack of a break; after a case bad practice?
Falling through by omitting the break can also lead to maintenance/debugging issues, but I don't consider it bad practice. It is, after all, intrinsic in the design of the switch statement. A fall through comment is always welcome so that the next guy - or you, revisiting your code months later - knows that the fall-through is intentional.
Is there a way to mechanically translate goto statements to if, switch, while, break, and continue statements, etc, or with function calls, objects, anything?
While it is not a good idea, it is possible using loops and swith-case. In the following example the goto variable decides what label (0, 1, 2 or default) to goto when you get to a continue.
int goTo=0;
while(true){
switch(goTo){
case 0:
doSomething();
goTo = 1;
continue;
case 1:
doSomethingElse();
goTo = 2;
continue;
case 2:
doSOmethingDifferent();
goTo = 0;
continue;
default:
return;
}
}
I thought this would be worth sharing here. I saw this on Reddit one day, it's an implementation of goto to an arbitrary line number (in the same .java file) via a custom class loader. It's a fun piece of code. http://steike.com/tmp/goto.zip . I take no credit for it.
Edit:
For those who are curious but don't want to download the zip and run it, for the following file:
public class GotoDemo {
public static void main(String[] args) {
int i = 5;
System.out.println(i);
i = i - 1;
if (i >= 0) {
GotoFactory.getSharedInstance().getGoto().go(4);
}
try {
System.out.print("Hell");
if (Math.random() < 2) throw new Exception();
System.out.println("World!");
} catch (Exception e) {
System.out.print("o ");
GotoFactory.getSharedInstance().getGoto().go(13);
}
}
}
It will print:
3
2
1
0
Hello World!
Considering the complexity that goto's can create based on where its jumping between, it's very doubtful.
The Java language doesn't support the features necessary to simulate gotos to arbitrary position (not even within the same method). You can implement a few simple uses of goto using the constructs you mentioned, but can't implement all possible goto uses this way. (*)
On the byte code level you could probably implement goto (at least within a method), but that byte code could not be mapped back to valid Java code in this case.
As for gotos that cross method or object boundaries: That's definitely a big no-no on the JVM level. The entire Java security model depends on the fact that code is verifyable and thus has only defined entry points (also known as "methods").
(*) Disclaimer: this assumes that you don't want to completely restructure the method to implement the effect of goto, which could also invoke code duplication and obfuscating the "normal" flow of the method. Since you can implement a turing machine in a Java method you can definitely implement "goto" in a Java method ;-)
Sure: (abbreviating slightly for clarity)
int goTo = 0; boolean done = false;
while (!done) {
switch (goTo) {
default:
case 1: System.out.println("We're at line 1!"); goTo = 2; break;
case 2: System.out.println("We're going to line 4!"); goTo = 4; break;
case 3: System.out.println("We're at line 3 and we're done!"); done = true; break;
case 4: System.out.println("We're at 4, going to 2! Screw you, line 3!"); goTo = 2; break;
}
}
Why you would want to do such a thing is beyond me, but hey, you can...
Yes, using a combination of the methods you mentioned...it is possible (anything is possible really, just figuring out how to do it properly is a pain in the ass).
Keep in mind that goto's can result in extremely complex execution paths...and therefore may result in unsightly large amounts of duplicate code in whatever is generated.
In practice, I imagine any given example goto can be translated to something else, particularly if method extraction is an allowed transformation. Is this an abstract question or do you actually have so many goto's that you really need an actual tool? Perhaps the java code itself was machine-translated from something?
I used to put one actual goto into every program I wrote just to annoy the purists.