Switch with if, else if, else, and loops inside case - java

For the purpose of my question I've only included case 1, but the other cases are the same. Let's say value is currently 1, we go to case 1 and our for loop goes through the array to see if each element matches with the whatever_value variable. In this case if it does, we declare the value variable to be equal to 2, and we break out of the loop. The problem is that when i highlight the other break(in eclipse), it says that the breaks are attached to the for statement as well, but i only wanted the for statement to be attached to the if statement, not the else if statements as well. I thought because there are no brackets for the for statement that it would only loop for the if statement but eclipse says otherwise(else if also loops from 0 to the length of the array).
switch (value) {
case 1:
for (int i = 0; i < something_in_the_array.length; i++)
if (whatever_value == (something_in_the_array[i])) {
value = 2;
break;
} else if (whatever_value == 2) {
value = 3;
break;
} else if (whatever_value == 3) {
value = 4;
break;
}
break;
case 2:
// code continues....

Your problem..... I think is that your for loop is encompassing all of the if, else if stuff - which acts like one statement, like hoang nguyen pointed out.
Change to this. Note the brackets that denote the code block on which the for loop operates and the change of the first else if to if.
switch(value){
case 1:
for(int i=0; i<something_in_the_array.length;i++) {
if(whatever_value==(something_in_the_array[i])) {
value=2;
break;
}
}
if(whatever_value==2) {
value=3;
break;
}
else if(whatever_value==3) {
value=4;
break;
}
break;
case 2:
code continues....

In this case, I'd recommend using break labels.
http://www.java-examples.com/break-statement
This way you can specifically call it outside of the for loop.

Seems like kind of a homely way of doing things, but if you must...
you could restructure it as such to fit your needs:
boolean found = false;
case 1:
for (Element arrayItem : array) {
if (arrayItem == whateverValue) {
found = true;
} // else if ...
}
if (found) {
break;
}
case 2:

If you need the for statement to contain only the if, you need to remove its else, like this:
for(int i=0; i<something_in_the_array.length;i++)
if(whatever_value==(something_in_the_array[i]))
{
value=2;
break;
}
/*this "else" must go*/
if(whatever_value==2)
{
value=3;
break;
}
else if(whatever_value==3)
{
value=4;
break;
}

but i only wanted the for statement to be attached to the if statement, not the else if statements as well.
Well get rid of the else then. If the else if is not supposed to be part of the for then write it as:
for(int i=0; i<something_in_the_array.length;i++)
if(whatever_value==(something_in_the_array[i]))
{
value=2;
break;
}
if(whatever_value==2)
{
value=3;
break; // redundant now
}
else if(whatever_value==3)
{
value=4;
break; // redundant now
}
Having said that:
it is not at all clear what you are really trying to do here,
not having the else part in the loop doesn't seem to make a lot of sense here,
a lot of people (myself included) think it is to always use braces ... so that people don't get tripped up by incorrect indentation when reading your code. (And in this case, it might help us figure out what you are really trying to do here ...)
Finally, braces are less obtrusive if you put the opening brace on the end of the previous line; e.g.
if (something) {
doSomething();
}
rather than:
if (something)
{
doSomething();
}

Related

Optimization for: while (true)

I'm using a
while (true)
{
if (x == y)
{
break;
}
else
{
//do stuff
}
}
loop like so, the frame is just an example frame, as the actual code itself is convoluted and overly complicated that it requires a "break;" statement in multiple different areas for multiple different conditions.
My question is; Is there a way to write a loop statement without the loop checking for a condition at all? Is there a more efficient way to write an infinite loop other than while(true)?
edit: (java)
edit2:
while (a < b)
{
while (true)
{
if (c < d)
{
if (e == null)
{
//do alot of stuff
break;
}
else
{
//do something
}
}
else if (d > c)
{
if (e == null)
{
//do alot of stuff
break;
}
else
{
//do something
}
}
else if (d == c)
{
break;
}
}
a = a + 1;
}
Is there a way to write a loop statement without the loop checking for a condition at all? Is there a more efficient way to write an infinite loop other than while(true)?
You can write an infinite loop in multiple ways, but they are all equivalent. Neither is really more efficient than the others:
while (true) { ... }
do { ... } while (true);
for (;;) { ... }
Depending on the actual code, it may make sense to reverse the "break-loop-logic" into "continue-loop-logic", as in:
boolean continueLoop;
do {
continueLoop = false;
// ... do stuff ...
if ( some condition ) {
continueLoop = true;
}
// ... do stuff ...
} while (continueLoop);
For your particular example, you may move the logic for breaking in the if statement to the while condition:
while (x != y) {
// do stuff
}
In fact, if your original while loop had multiple conditions for breaking, you might be able to move them all to the while condition, e.g.
while (!cond1 && !cond2 ... ) {
// execute
}
Yes there are a lot ways you can do this. For example you can declare a variable outside a loop put a condition based on variable value and reset that variable inside a loop, hence loop will run infinitely without checking internal conditions.
Read this for examples :-
https://en.wikipedia.org/wiki/Infinite_loop

multiple if statements and a loop

I have a logical problem. I will provide pseudo code since the real code isn't all that readable. I want to only enter one of the instructions, and if none of the instructions are reachable I want the function to break out from the loop.
I'm pretty new to programming so any help is appreciated.
edit: In every iteration I want to only reach one of the conditions. Since there is a loop going on for a longer time I want to be able to reach the same / other instructions for every iteration
while(true){
if(condition){ // Instruction 1
do stuff
}else{
do stuff
}
if(condition){ // Instruction 2
do stuff
}else{
do stuff
}
if(condition){ // Instruction 3
do stuff
}else{
do stuff
}
if(condition){ // Instruction 4
do stuff
}else{
do stuff
}
if(none condition){
break;
}
}
I don't think anyone's got this spot on so far so I'll throw in my understanding of what you're asking.
while(true) // keep looping
{
boolean instructionExecuted = false; // we haven't done an instruction this iteration
// Instruction 1
if(condition) {
instructionExecuted = true;
//do stuff
} else {
//do stuff
}
// Instruction 2
if(condition && !instructionExecuted) { // If we've not done an instruction,
// and we can do instruction #2
instructionExecuted = true;
//do stuff
} else if (!instructionExecuted) { // only do this if we haven't already
// done an instruction
//do stuff
}
// Instruction 3
if(condition && !instructionExecuted) { // If we've not done an instruction,
instructionExecuted = true; // and we can do instruction #3
//do stuff
} else if (!instructionExecuted) { // only do this if we haven't already
// done an instruction
//do stuff
}
//etc.
if(none condition)
{
break;
}
}
Adding a bool trigger might be what you are looking for. if you enter any if statements turn the trigger to true.
You're making this harder than it has to be. All you need to do is have an if statement with multiple else if statements after it.
Example:
if (condition) {
doStuff();
} else if (condition) {
doStuff();
} else if (condition) {
...
} else {
break;
}
well, there are multiple ways to accomplish what you want:
Introduce a top-level boolean flag doNotBreak and set true in if/else blocks execution of which means the loop should not break.
Check should it break or not by combining conditions using in the loop: if(condition1 && !condition2 && ..) break;
Instead of the last condition, break with condition and inside if/else block where you don't want to break, use continue.
boolean reachable = false;
while(true){
if(condition){ // Instruction 1
do stuff
reachable = true
}else{
do stuff
}
if(condition){ // Instruction 2
do stuff
reachable = true
}else{
do stuff
}
if(condition){ // Instruction 3
do stuff
reachable = true
}else{
do stuff
}
if(condition){ // Instruction 4
do stuff
reachable = true
}else{
do stuff
}
if(!reachable){
break;
}
}
Alternatively you can check if it is possible to use switch Statements instead of if-else. Example
public static void main(String argv[]) {
String [] conditions = {"condition_1","condition_2","condition_3","condition_4","xyz"};
printConditionType(conditions);
}
public static void printConditionType(String [] conditions){
int i = 0;
while (i<conditions.length){
switch (conditions[i]) {
case "condition_1":
System.out.println("#1");
break;
case "condition_2":
System.out.println("#2");
break;
case "condition_3":
System.out.println("#3");
break;
case "condition_4":
System.out.println("#4");
break;
default:
System.out.println("Invalid condition:" + conditions[i]);
}
i++;
}
}

In Java, is there some kind of coding method that's better than excessive if..else statements?

Currently, I have a large plot of Java code that works perfectly. In it, I have a ton of various if...else statements gathered. Is there a more efficient way of having the same logic as a lot if...else statements w/out having such a jumbled file? Perhaps w/ cases?
What I have currently is something along these lines:
int input = (some numeric value);
if (input == 0) { ... } else { ... }
if (input == 1) { ... } else { ... }
/* And so on and so forth */
switch(someVar) {
case someConstant:
//code
break;
case someOtherConstant:
//code
break;
default:
//code
break;
}
You can add as many cases as you want. And note that "someConstant" must be a constant (final) value. As far as I know, you cannot use variables for cases.
Yes! This looks like a great time to use the switch statement -
switch (input) {
case 0: /* do something */ break;
case 1: /* do something else */ break;
default: /* do a third something */ break;
}

Won't this just break out of the if statement?

So basically given the below code.
When action = 2; and mode = 1 Will i ever be set to 2?
I am working on a colleagues code, and it is written like this, but I thought that break would just skip the if and continue the rest of case 2. So basically the if statement is pointless.
switch(action){
case 1: i = 1; break;
case 2: if(mode == 1)
{
break;
}
i = 2;
break;
case 3: i = 3; break;
Ive rewritten this as:
case 2: if(mode != 1)
i = 2;
break;
But it is not the only place, and some more complex. If im going to refactor it I need some info that I am correct.
There's no such a thing as an "if loop." Break can never refer to an "if" statement.
See Wasserman's answer for a pointer to the language specification.
Also, assuming that 1 <= action <= 3, your code simplifies to:
if(! (action == 2 && mode == 1)) {
i = action;
}
JLS section 14.15:
A break statement transfers control out of an enclosing statement.
BreakStatement:
break Identifieropt ;
A break statement with no label attempts to transfer control to the innermost enclosing switch, while, do, or for statement (emphasis added) of the immediately enclosing method or initializer block; this statement, which is called the break target, then immediately completes normally.
your refactoring is correct if that's what you want to know.
If action == 2 and mode == 1, i = 2 will not be executed (why you don't test it? It would be faster than asking here).
But your improvement is anyways cleaner, I would use it.

Optimizing if-else /switch-case with string options

What modification would bring to this piece of code? In the last lines, should I use more if-else structures, instead of "if-if-if"
if (action.equals("opt1"))
{
//something
}
else
{
if (action.equals("opt2"))
{
//something
}
else
{
if ((action.equals("opt3")) || (action.equals("opt4")))
{
//something
}
if (action.equals("opt5"))
{
//something
}
if (action.equals("opt6"))
{
//something
}
}
}
Later Edit: This is Java. I don't think that switch-case structure will work with Strings.
Later Edit 2:
A switch works with the byte, short,
char, and int primitive data types. It
also works with enumerated types
(discussed in Classes and Inheritance)
and a few special classes that "wrap"
certain primitive types: Character,
Byte, Short, and Integer (discussed
in Simple Data Objects ).
Even if you don't use a switch statement, yes, use else if to avoid useless comparison: if the first if is taken, you don't want all others ifs to be evaluated here since they'll always be false. Also you don't need indenting each if making the last block being so indented that you can't see it without scrolling, the following code is perfectly readable:
if (action.equals("opt1")) {
}
else if (action.equals("opt2")) {
}
else if (action.equals("opt3")) {
}
else {
}
Use a dictionary with string as key type and delegates* as value type.
- Retrieving the method from using the string will take O(1+load).
Fill the dictionary within the class's constructor.
Java does not support delegate, so as a work around you may need to define a few inner classes - one for each case and pass the instance of the inner classes instead of the methods as values.
Use a switch statement assuming your language supports switching on a string.
switch(action)
{
case "opt6":
//
break;
case "opt7":
//
...
...
...
}
There are a number of ways to do this in Java, but here's a neat one.
enum Option {
opt1, opt2, opt3, opt4, opt5, opt6
}
...
switch (Option.valueOf(s)) {
case opt1:
// do opt1
break;
case opt2:
// do opt2
break;
case opt3: case opt4:
// do opt3 or opt4
break;
...
}
Note that valueOf(String) will throw an IllegalArgumentException if the argument
is not the name of one of the members of the enumeration. Under the hood, the implementation of valueOf uses a static hashmap to map its String argument to an enumeration value.
You can use a switch.
switch (action)
{
case "opt3":
case "opt4":
doSomething;
break;
case "opt5":
doSomething;
break;
default:
doSomeWork;
break;
}
It could help if you specified the language... As it looks like C++, you could use switch.
switch (action) {
case "opt1":
// something
break;
case "opt2":
// something
break;
...
}
And in case you want to use if statements, I think you could improve readability and performance a bit if you used "else if" without the curly braces, as in:
if (action.equals("opt1")) {
//something
} else if (action.equals("opt2")) {
//something
} else if ((action.equals("opt3")) || (action.equals("opt4"))) {
//something
} else if (action.equals("opt5")) {
//something
} else if (action.equals("opt6")) {
//something
}
I think some compilers can optimize else if better than a else { if. Anyways, I hope I could help!
I would just clean it up as a series of if/else statements:
if(action.equals("opt1"))
{
// something
}
else if (action.equals("opt2"))
{
// something
}
else if (action.equals("opt3"))
{
// something
}
etc...
It depends on your language, but it looks C-like, so you could try a switch statement:
switch(action)
{
case "opt1":
// something
break;
case "opt2":
// something
break;
case "opt3":
case "opt4":
// something
break;
case "opt5":
// something
break;
case "opt6":
// something
break;
}
However, sometimes switch statements don't provide enough clarity or flexibility (and as Victor noted below, will not work for strings in some languages). Most programming languages will have a way of saying "else if", so rather than writing
if (condition1)
{
...
}
else
{
if (condition2)
{
...
}
else
{
if (condition3)
{
...
}
else
{
// This can get very indented very fast
}
}
}
...which has a heap of indents, you can write something like this:
if (condition1)
{
...
}
else if (condition2)
{
...
}
else if (condition3)
{
...
}
else
{
...
}
In C/C++ and I believe C#, it's else if. In Python, it's elif.
The answers advising the use of a switch statement are the way to go. A switch statement is much easier to read than the mess of if and if...else statements you have now.
Simple comparisons are fast, and the //something code won't executed for all but one case, so you can skip "optimizing" and go for "maintainability."
Of course, that's assuming that the action.equals() method does something trivial and inexpensive like a ==. If action.equals() is expensive, you've got other problems.
Procedural switching like this very often is better handled by polymorphism - rather than having an action represented by a string, represent an action by an object who has a 'something' method you can specialise. If you find you do need to map a string to the option, use a Map<String,Option>.
If you want to stick to procedural code, and the options in your real code really are all "optX":
if ( action.startsWith("opt") && action.length() == 4 ) {
switch ( action.charAt(3) ) {
case '1': something; break;
case '2': something; break;
case '3': something; break;
...
}
}
which would be OK in something like a parser ( where breaking strings up is part of the problem domain ), and should be fast, but isn't cohesive ( the connection between the object action and the behaviour is based on the parts of its representation, rather than anything intrinsic in of the object ).
In fact this depends on branch analysis. If 99% of your decisions are "opt1" this code is already pretty good. If 99% of your decisions are "opt6" this code is ugly bad.
If you got often "opt6" and seldom "opt1" put "opt6" in the first comparison and order the following comparisons according to the frequency of the strings in your execution data stream.
If you have a lot of options and all have equal frequency you can sort the options and split them into a form of a binary tree like this:
if (action < "opt20")
{
if( action < "opt10" )
{
if( action == "opt4" ) {...}
else if( action == "opt2" ) {...}
else if( action == "opt1" ) {...}
else if( action == "opt8" ) {...}
}
}
else
{
if( action < "opt30 )
{
}
else
{
if( action == "opt38" ) {...}
else if( action == "opt32" ) {...}
}
}
In this sample the the range splits reduces the needed comparisons for "opt38" and "opt4" to 3. Doing this consequent you get log2(n) +1 comparisons in every branch. this is best for equal frequencies of the options.
Don't do the binary spit to the end, at the end use 4-10 "normal" else if constructs that are ordered by the frequency of the options. The last two or three levels in a binary tree don't take much advance.
Summary
At least there are two optimizations for this kind of comparisons.
Binary Decision Trees
Ordering due to the frequency of the options
The binary decision tree is used for large switch-case constructs by the compiler. But the compiler don't know anything about frequencies of an option. So the ordering according to the frequencies can be a performance benefit to the use of switch-case if one or two options are much more frequent than others. In this case this is a workaround:
if (action == "opt5") // Processing a frequent (99%) option first
{
}
else // Processing less frequent options (>1%) second
{
switch( action )
{
case "opt1": ...
case "opt2": ...
}
}
Warning
Don't optimize your code until you have done profiling and it is really necessary. It is best to use switch-case or else-if straight forward and your code keeps clean and readable. If you have optimized your code, place some good comments in the code so everybody can understand this ugly peace of code. One year later you won't know the profiling data and some comments will be really helpful.
If you find the native java switch construct is too much limiting give a glance to the lambdaj Switcher that allows to declaratively switch on any object by matching them with some hamcrest matchers.
Note that using strings in the cases of a switch statement is one of the new features that will be added in the next version of Java.
See Project Coin: Proposal for Strings in switch

Categories

Resources