if-else structure - java

I have these long statements that I will refer to as x,y etc. here.
My conditional statements' structure goes like this:
if(x || y || z || q){
if(x)
do someth
else if (y)
do something
if(z)
do something
else if(q)
do something
}
else
do smthing
Is there a better, shorter way to write this thing? Thanks

I don't see a big problem with how you write it now.
I do recommend using curly braces even for single statement if-blocks. This will help you avoid mistakes in case you have to add more code lines later (and might forget to add the curly braces then). I find it more readable as well.
The code would look like this then:
if (x || y || z || q) {
if (x) {
do something
} else if (y) {
do something
}
if (z) {
do something
} else if (q) {
do something
}
} else {
do something
}

Another variant that avoids the multiple checks and the errorprone complex logical expressions might be:
boolean conditionhandled = false;
if (x) {
do something
conditionhandled = true;
} else if (y) {
do something
conditionhandled = true;
}
if (z) {
do something
conditionhandled = true;
} else if (q) {
do something
conditionhandled = true;
}
if (!conditionhandled) {
do something
}

This seems pretty clear to me (and clear is good).
What you can do is first evaluate x,y,z and q and store those as variables so you don't have to do that twice.

Maybe this is a little easier to read. But now you will perform one extra check. If it is not mission critical code then maybe you can use the following:
if (x)
do something;
else if (y)
do something;
if (z)
do something;
else if(q)
do something;
if !(x || y || z || q)
do something completely different.

I'm not recommending the following, in fact, I think what you got is fine, but:
s = true;
if (x) {
do something;
s = false;
} else if (y) {
do something;
s = false;
}
if (z) {
do something;
s = false;
} else if (q) {
do something;
s = false;
}
if (s) {
so something;
}

Can you make some assumptions about x,y,z,q?
e.G. just one of them can be true. Than you could see it as a State
enum State {
X{
void doSomething(){
doItTheXWay();
}
},
Y{
void doSomething(){
doItTheYWay();
}
},
Z{
void doSomething(){
doItTheZWay();
}
},
Q{
void doSomething(){
doItTheQWay();
}
};
void doSomething(){
}
}
and in your code where you used the if statements
you could assign a state and just do the right thing
State state = getAState();
state.doSomething();
In case you don't like enums State could be an Interface and X to Q could be implementing classes.
The benefits in this case are in multiple usage of the same if else construct. Say some codelines later you would begin with
if(x)
do_the_next_thing_with_X();
...
or you could just extend your enum with another function and make one single call
state.doTheNextThing();

Related

Efficiently Check Multiple Conditions [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I've got a situation in which I need to check multiple conditions, where every combination has a different outcome. In my specific condition, I've got 2 variables, which are enum types, that can each be 2 different values.
enum Enum1
{
COND_1,
COND_2
}
enum EnumA
{
COND_A,
COND_B
}
Enum1 var1;
EnumA varA;
This gives me 4 possible conditions, which requires 4 different outcomes. I've come up with a few different ways of doing this, either using if statements or switch statements:
if(var1 == Enum1.COND_1 && varA == EnumA.COND_A)
{
// Code
}
else if(var1 == Enum1.COND_1 && varA == EnumA.COND_B)
{
// Code
}
else if(var1 == Enum1.COND_2 && varA == EnumA.COND_A)
{
// Code
}
else if(var1 == Enum1.COND_2 && varA == EnumA.COND_B)
{
// Code
}
Or:
switch(var1)
{
case COND_1:
switch(varA)
{
case COND_A:
// Code
break;
case COND_B:
// Code
break;
}
break;
case COND_2:
switch(varA)
{
case COND_A:
// Code
break;
case COND_B:
// Code
break;
}
break;
}
I've thought of others, but don't want to fill this up with code :P I'd like to know what the best way to do this is. I think the switch is a bit easier to read, but the ifs are shorter. I think it'd be really cool if switches could have multiple conditions, but I haven't heard of it. This also begs the question: what's the best way to do this with an arbitrary number of variables and possible values?
For your small use case I would probably go for nested if statements. But if you have plenty of enum constants, perhaps a pattern using streams could make your code easier to read and maintain (for a small performance penalty). You could solve it using a stream like this:
Stream.of(new Conditional(COND_1, COND_A, () -> {/* do something */}),
new Conditional(COND_1, COND_B, () -> {/* do something */}),
new Conditional(COND_2, COND_A, () -> {/* do something */}),
new Conditional(COND_2, COND_B, () -> {/* do something */}))
.filter(x -> x.test(var1, varA))
.findAny()
.ifPresent(Conditional::run);
That would require a supporting class:
class Conditional implements BiPredicate<Enum1, EnumA>, Runnable
{
private final Enum1 var1;
private final EnumA varA;
private final Runnable runnable;
public Conditional(Enum1 var1, EnumA varA, Runnable runnable) {
this.var1 = var1;
this.varA = varA;
this.runnable = runnable;
}
#Override
public boolean test(Enum1 enum1, EnumA enumA) {
return var1 == enum1 && varA == enumA;
}
#Override
public void run() {
runnable.run();
}
}
Performance differences are probably negligible here, so I would focus on shortness and readability. So I would just simplify the if's a bit by using temporary variables:
boolean is_1 = (var1 == Enum1.COND_1);
boolean is_A = (varA == EnumA.COND_A);
if(is_1 && is_A)
{
// Code
}
else if(is_1 && !is_A)
{
// Code
}
else if(!is_1 && is_A)
{
// Code
}
else if(!is_1 && !is_A)
{
// Code
}
I prefer the if variant without nesting, since it is short and you have all the conditions in one line.
When stopping through the code during debugging, it can get tedious though, since you have to step over all preceding conditions, which is O(n). When executing the code, this shouldn't matter since the compiler will probably optimize the code.
There is no obvious best way, so you will have to experiment a bit.
I definitely prefer the flat version, it could just use a little less duplication:
// If you can't make the variables final, make some final copies
final Enum1 var1 = Enum1.COND_2;
final EnumA varA = EnumA.COND_B;
class Tester { // You could also make an anonymous BiPredicate<Enum1, EnumA>
boolean t(Enum1 v1, EnumA vA) {
return var1 == v1 && varA == vA;
}
};
Tester tes = new Tester();
if (tes.t(Enum1.COND_1, EnumA.COND_A)) {
// code
} else if (tes.t(Enum1.COND_1, EnumA.COND_B)) {
// code
} else if (tes.t(Enum1.COND_2, EnumA.COND_A)) {
// code
} else if (tes.t(Enum1.COND_2, EnumA.COND_B)) {
// code
}
Run it here. You could maybe make it even shorter and less redundant by doing a static import of the enums to avoid mentioning the enum names, e.g. tes.t(COND_1, COND_B). Or if you're willing to give up some compile time safety you can pass a string which gets converted to the two enum values, e.g. tes.t("COND_1 COND_A") (the implementation is left to the reader).
Maybe crazy idea but you could construct an int or a byte using the flags and use it in a single switch.
private int getIntegerStateForConditions(boolean... conditions ){
int state = 0;
int position = 0;
for(boolean condition: conditions){
if(condition){
state = state || (1 << position++);
}
}
return state;
}
...
switch(getIntegerStateForCondition((var1 == Enum1.COND_1), (var2 == EnumA.COND_A)){
case 0: ... //both condition false
case 1: ... //first condition true second false
case 2: ... //first false, second true ...
}
...
I think this is very far from being clean code but it looks better.
If I were you I would rely on bit flags in order to have only one byte (as you have only 4 use cases) to deal with and use a switch statement on this byte to manage all your use cases.
Something like this:
private static final int COND_2 = 1;
private static final int COND_B = 2;
private byte value;
public void setValue(Enum1 enum1) {
if (enum1 == Enum1.COND_1) {
this.value &= ~COND_2;
} else {
this.value |= COND_2;
}
}
public void setValue(EnumA enumA) {
if (enumA == EnumA.COND_A) {
this.value &= ~COND_B;
} else {
this.value |= COND_B;
}
}
public Enum1 getEnum1() {
return (this.value & COND_2) == COND_2 ? Enum1.COND_2 : Enum1.COND_1;
}
public EnumA getEnumA() {
return (this.value & COND_B) == COND_B ? EnumA.COND_B : EnumA.COND_A;
}
Then your tests would be:
switch (value) {
case 0 :
// 1-A;
break;
case 1 :
// 2-A;
break;
case 2 :
// 1-B;
break;
case 3 :
// 2-B;
break;
}
I would personally prefer this:
if(understandableNameInContextName1(var1, varA))
{
// Code
}
else if(understandableNameInContextName2(var1, varA))
{
// Code
}
else if(understandableNameInContextName3(var1, varA))
{
// Code
}
else if(understandableNameInContextName4(var1, varA))
{
// Code
}
private boolean understandableNameInContextName1(Object var1, Object varA){
return (var1 == Enum1.COND_1 && varA == EnumA.COND_A);
}
private boolean understandableNameInContextName2(Object var1, Object varA){
return (var1 == Enum1.COND_1 && varA == EnumA.COND_B);
}
private boolean understandableNameInContextName3(Object var1, Object varA){
return (var1 == Enum1.COND_2 && varA == EnumA.COND_A);
}
private boolean understandableNameInContextName4(Object var1, Object varA){
return (var1 == Enum1.COND_2 && varA == EnumA.COND_B);
}
And the names of the methods could be like, isOrderShippedAndDelivered(), isRequestSendAndAckRecieved().
The reason is that this is going to make the code a lot more readable.
Unless you have data that leads you back to these if statement there is not going to be much gain optimizing these.
See:
https://softwareengineering.stackexchange.com/questions/80084/is-premature-optimization-really-the-root-of-all-evil
Kind of depends on the complexity of the code and number of combinations but another option is a dictionary with the key comprising a Tuple of your enumerations and a value of a delegate to the code.

How to return a break or Continue in a method is it possible?

When I'm using while loop I need to use many if blocks which are exactly same So I planed to put it in a method and reuse it where I want! but I had a problem I want to return Continue or break in some area of my if blocks so can I return Break or continue?
while (true){
move(a);
move(b);
}
public *** move(Parameter parameter){
if (statement){
return continue;
}
else{
return break;
}
}
You can return a boolean:
while (true){
if(move(a))
{
break;
}
else
{
continue;
}
if(move(b))
{
break;
}
else
{
continue;
}
}
public boolean move(Parameter parameter){
if (statement){
return false;
}
else{
return true;
}
}
I'm going to set aside the fact if we implemented what you want literally then move(b); would be unreachable. Presumably when you say continue you mean execute the next statement; not return to the start of the loop?
But sadly you can't achieve this in Java. In Java, you can only return a value, not an "instruction". (In C and C++ you can contrive this using a macro, although that messes up your debugger.)
However, if you adapt move to return a boolean which is say true if you want to break and false otherwise, then at the call site you could write
while (true){
if(move(a)){
break;
} else if (move(b)){
break;
}
}
or ace it with
while (true){
if (move(a) || move(b)){
break;
}
}
where I'm exploiting the short-circuiting nature of the operator ||.
Finally, if you want to submit this code to an obfuscation contest then use the simply beautiful but still comprehensible
while (!(move(a) || move(b)));
and if you want to guarantee that you win said contest, then swap the return rule of move round and use the utterly indecent
while (move(a) && move(b));
Make it super simple with a returning boolean
public boolean move(Parameter parameter){
return statement;
}
while (true){
if(!move(a)) break;
if(!move(b)) break;
}

Simplify multiple if-else statements for unit testing

I am writing some java code to check multiple conditions by if-else. The code is working properly but it is hard to do unit test.
reads lines that contains keyword conditionOne, conditionTwo or other keywords. hasConditionOneEnabled and hasConditionTwoEnabled are boolean values.
My real code has more else if statements than the provide example.
Can anyone help? Or give me some hint how to make the code shorter then I can write unit test easier? Thanks
boolean a = false;
boolean b = false;
if(line.contains("conditionOne")){
if(hasConditionOneEnabled){
a = true;
}else{
b = true;
}
}else if (line.contains("conditionTwo")){
if(hasConditionTwoEnabled){
a = true;
}else{
b = true;
}
}else{
a = true;
b = true;
}
if(a && b){
// do something 1
}else if(!a && b){
// do something 2
}else if(a && !b){
// do something 3
}else{
//both false, do nothing
}
a and b cannot be both false after the set of if-else statements.
In the first two if's variable a will have the same value than the corresponding hasConditionXXEnabled and b will be set as the opposite. The default else will set both to true.
Consider the following code:
a = true;
b = true;
if(line.contains("conditionOne")){
a = hasConditionOneEnabled;
b = !a;
}
else if(line.contains("conditionTwo")){
a = hasConditionTwoEnabled;
b = !a;
}
if(a && b){
// do something 1
}
else if(b){
// do something 2
}
else{
// do something 3
}
// test it on different line String input and different int value returned...
int xxx(String line) {
if(line.contains("conditionOne")){
status = hasConditionOneEnabled?0:1;
} else if (line.contains("conditionTwo")){
status = hasConditionTwoEnabled?0:1;
} else{
status = -1;
}
return status;
}
// test it base on different status value..
switch (status) {
case 0: ...;
case 1: ...;
default: ...;
}
However, if your if-else pattern can be continuously repeat after some modification, you may just create different boolean funciton for it.
First of all both a and b can never be false, so your last else statement is redundant.
Your entire set of conditional statements can be reduced to an if - else if - else block. You don't need variables a and b since you are using them to do something else anyway. Besides vague variables names like a and b hinder readability.
Let me first show you the code and I'll walk you through it subsequently.
boolean lineContainsCond1 = line.contains("conditionOne");
boolean lineContainsCond2 = line.contains("conditionTwo");
boolean lineContainsNeitherCondition = !lineContainsCond1 && !lineContainsCond2;
boolean conditionsForSomething3 = (lineContainsCond1 && conditionOneEnabled) || (lineContainsCond2 && conditionTwoEnabled);
if(lineContainsNeitherCondition)
//do something 1 (Note: this is the same something 1 from your code)
else if(conditionsForSomething3)
//do something 3
else
//do something 2
lineContainsNeitherCondition is essentially both a and b being true in your code.
conditionsForSomething3 tantamounts to a!b.
If both lineContainsNeitherCondition and conditionsForSomething3 are false, we can derive the following conclusions:
Given lineContainsNeitherCondition is false, either lineContainsCond1 is true or lineContainsCond2 is true
Case 1 : lineContainsCond1 is true:
In this case, either conditionOneIsEnabled is true or conditionOneEnabled is false. If it were true, then conditionFOrSomething3 cannot be false, if it's false, then that leads to lineContainsCond && !conditionOneEnabled to be true which leads to b!a in the original code and thereby executes //something 2.
A similar argument can be made for Case 2 : lineContainsCond2 is true.
Why don't reduce the amount of if else statements in your code.
Try replacing the if else statements with private methods that return a boolean. Try to in cooperate the below methods or similar methods into your above code.
Having a look at mookito great for mocking and stubbing. If you have a big project with lots of Objects will save you hours maybe days.
private boolean doesLineContainCondition(String line, String searchPhrase) {
if(line.contains(searchPhrase) {
return true;
} else {
return false;
}
}
private boolean hasConditionBeenEnabled(boolean condition) {
if(condition) {
a = true;
}
else {
b= true;
}
}

Java return statement

Eclipse keeps telling me to add a return statement to the method, even though I did so.
public class PrefixCode {
public String isOne(String[] words) {
if(words.length==1) {
return "Yes";
}
ArrayList<Integer> indexPositions= new ArrayList<Integer>();
for(int i=0;i<words.length;i++) {
String firstWord=words[i];
java.util.List<String> listOfWordsToCheck = new ArrayList<String>(Arrays.asList(words));
listOfWordsToCheck.set(i,null);
for(int j=0;j<listOfWordsToCheck.size();j++) {
String secondWord= listOfWordsToCheck.get(j);
if(firstWord.startsWith(secondWord)==true) {
indexPositions.add(j);
}
else if(firstWord.startsWith(secondWord)==false);
}
}
if(indexPositions.size()==0) {
return "Yes";
}
else if(indexPositions.size()!=0) {
Collections.sort(indexPositions);
return "No,"+indexPositions.get(0)+"";
}
}
}
My return statements are outside of the for loops, so I don't understand what's wrong here.
There is no default return. The only returns you are making are if some conditions are true. What if the conditions are false?
Add a return after the last else block and you are all good to go.
The else block is redundant. What lies inside the else block should be be without else.
Since you have added if, else if, you need to else to that control flow to satisfy the compiler. Logically, size can be either zero or more than zero. So, you need to have if and else part only
if(indexPositions.size()==0){
return "Yes";
} else if(indexPositions.size()!=0){
Collections.sort(indexPositions);
return "No,"+indexPositions.get(0)+"";
} else {
// return what?
}
You can simplify this logic by,
if(indexPositions.size() == 0) {
return "Yes";
} else { //size more than zero
Collections.sort(indexPositions);
return "No,"+indexPositions.get(0) + "";
}
you should use else instead of
else if(indexPositions.size() != 0) {
Collections.sort(indexPositions);
return "No,"+indexPositions.get(0) + "";
}
The compiler doesn't know if the if conditions are going to succeed. So, you need to add a default return out of those if (even if your if conditions cover all possible cases!)
One of the best practice is to have only one return at the method end! Like this:
public String isOne(String[] words) {
String isOne = null;
if(words.length==1){
isOne = "Yes";
}
...
if(indexPositions.size()==0){
isOne = "Yes";
}
else if(indexPositions.size()!=0){
Collections.sort(indexPositions);
isOne = "No,"+indexPositions.get(0)+"";
}
return isOne;
}
Sometimes you may initialize the variable with a default value too, even if in this case is not needed :
String isOne = "No";
In also in your code there is an "error", the indexPositions.size may only be 0 or more, so you may want to use else instead of else if, and complete the graph. In this case eclipse won't tell you to add a return statement anymore, even if you use the return inside the condition block.
if(indexPositions.size()==0) {
return "Yes";
}
else {
Collections.sort(indexPositions);
return "No,"+indexPositions.get(0)+"";
}
I usually do this by declaring a boolean at the start of the function and set it to false. If for whatever reason the function says that variable is gonna be true. I set the declared variable to true instead of returning true. At the end of the function i return that declared variable.
It then has its default return and if the variable was set to true, it returns true.

Is it possible to to declare variables within a condition?

This is how I would do a while loop:
boolean more = true;
while (more)
{
// do something
if (someTest())
{
more = false;
}
}
That's pretty standard. I'm curious to know if there's a way of doing something similar to the code below in Java: (I think I've seen something like it in C)
// The code below doesn't compile (obviously)
while (boolean more = true)
{
// do something
if (someTest())
{
more = false;
}
}
I only ask this because currently I don't like the way I'm defining the variable used in the condition (in this case: "more") outside the scope of the loop, even though it's only relevant inside the loop. There's no point it being left hanging around after the loop has finished.
* * Update * *
An idea came to me following a visit to the Porcaline Chamber of Secrets:
for (boolean more=true; more; more=someTest())
{
// do something
}
It's not perfect; It's abusing the for loop and I can't think of a way to execute the loop at least once, but it's close... Is there a way to make sure the loop is performed 1+ times?
To answer your question literally, you can do
for(boolean more = true; more; ) {
more = !someTest();
}
but this is much the same as
while(!someTest());
If it must execute at least once you can do
do {
} while(!someTest());
For your specific case, you can reduce your code to this:
while (true) {
if (someTest()) {
break;
}
}
In general, you could replace your outer-scope declaration with an inner-scope one, but you'd need to move the loop condition:
while (true) {
boolean more=true;
...
if (someTest()) {
more = false;
}
...
if (!more) {
break;
}
}
Or even:
do {
boolean more=true;
...
if (someTest()) {
more = false;
}
...
if (!more) {
break;
}
} while (true);
I'd opine that defining your condition outside the loop is clearer.
KidTempo, in the example you gave, I think that more would be re-initialized each time through the loop. Each time through the loop, the conditional is re-evaluated, so assuming that you are able to define a variable in a conditional, the variable would be re-initialized each time that conditional is re-evaluated. This would also apply to other types of conditionals, so I would say to avoid defining variables in a conditional.

Categories