-1

I'm facing huge problems with nested if conditions in our core java application An abstract of code is as below....we can have nearly 20 nested if conditions can you tell me how to optimize this piece of code ?

what is a better way of avoiding this nested if conditions in java.i can have 20 nested if conditions and that could be a huge problem from design perspective of Java Application.

Please help with a solution in java Java Version 1.6

String condition = getCondition();
if (condition.equals(add)) { // add operation
    add();
    if (condition.equals(sub)) {// sub operation
        sub();
        if (condition.equals(div)) { //div operation
            div();
            if (condition.equals(cos)) { // cos operation
                cos();
            }
        }
    }
}

EDIT: I can have more mathematical operations say 20 more,will switch work then.20 operations is a huge lot.

Kev
  • 118,037
  • 53
  • 300
  • 385
Deepak
  • 2,094
  • 8
  • 35
  • 48

7 Answers7

2

You should use if else-if condition instead like this:

String condition = getCondition();      
if(condition.equals(add))
    add();   
else if(condition.equals(sub)) 
    sub();   
else if(condition.equals(div))   
    div();   
else if(condition.equals(cos))   
    cos();  
Vishal K
  • 12,976
  • 2
  • 27
  • 38
1

Use switch statement instead. Use this when you have alot of decision.

Note that this can only happen with JDK 7 when you want to use a String in switch statement. In older version enum might be helpful.

tmwanik
  • 1,643
  • 14
  • 20
  • It's unfortunate that we don't know the types involved, or what version of Java the OP is using. This may or may not be appropriate - it would be worth being clear about this in your answer. – Jon Skeet Mar 16 '13 at 09:39
  • @JonSkeet,the version used is java 1.6 – Deepak Mar 16 '13 at 09:41
1

State Pattern :

public enum Operation {
ADD {
    int execute(int a, int b) {
        return a + b;
    }
},
SUB {
    int execute(int a, int b) {
        return a - b;
    }
},
MUL {
    @Override
    int execute(int a, int b) {
        return a * b;
    }
},
DIV {
    @Override
    int execute(int a, int b) {
        return a / b;
    }
};

abstract int execute(int a, int b);

public static void main(String[] args) {
    Operation oper = getOperation();
    oper.execute(3, 4);
}

private static Operation getOperation() {
    return Operation.MUL;
}

}

like this:

public static void main(String[] args) {
    String operation = user set it
    Operation oper = getOperation(operation);
    oper.execute(3, 4);
}

private static Operation getOperation(String operation) {
    return Operation.valueOf(operation.toUpperCase());
}

be careful that Operation.valueOf may throw NullPointerException if operation is null or IllegalArgumentException if operation is not one of Operation enum

BlackJoker
  • 3,099
  • 2
  • 20
  • 27
  • can you complete public static void main(String[] args) { String operation = user set it Operation oper = getOperation(operation); oper.execute(3, 4); } private static Operation getOperation(String operation) { return Operation.valueOf(operation.toUpperCase()); } – Deepak May 29 '22 at 16:07
  • How to handle NullPointerException if operation is null or IllegalArgumentException if operation is not one of Operation enum – Deepak May 29 '22 at 16:18
1

If the if statments do not need to be nested, then you can use a command pattern.

First, setup a mapping between matcher and commands. The commands adhere to a common invoke interface such as Runnable, Callable or as in my example Command. The example shows how to create the wrapper dynamically and using static or non static classes. This pattern is practical if the actual commands are not known before hand as it is possible to later add and remove commands.

public class CommandExample {

    private interface Command {
        public void execute();
    }

    private Map<String, Command> commands = new HashMap<>();

    private void setUp() {
        commands.put("add", new Command() {
            public void execute() {
                add();
            }
        });
        commands.put("sub", new Sub());
        commands.put("arg", new Argument("the argument"));
    }

    private void add() {
        System.out.println("Add called");
    }

    private static class Sub implements Command {
        @Override
        public void execute() {
            System.out.println("Sub called");
        }
    }

    private class Argument implements Command {

        private final String arg;

        public Argument(String arg) {
            this.arg = arg;
        }

        @Override
        public void execute() {
            System.out.println("Argument called with arg " + arg
                    + " and access to outer class " + CommandExample.this);
        }
    }

    private void execute(String... names) {
        for (String name : names) {
            Command command = commands.get(name);
            if (command != null) {
                command.execute();
            } else {
                System.err.println("Command '" + name
                        + "' is not known. Only know " + commands.keySet());
            }
        }
    }

    public static void main(String[] args) {
        CommandExample commandExample = new CommandExample();
        commandExample.setUp();
        commandExample.execute("add", "sub", "arg", "unknown");
    }
}
Roger Lindsjö
  • 11,330
  • 1
  • 42
  • 53
  • ,can you give a working example so that i can run in my system or you can post in www.ideone.com under java section – Deepak Mar 16 '13 at 10:50
  • @Deepak I think that the code works for the the example you have given (your methods take no argument). However, I'll try to make a complete example without exactly knowing what you need. – Roger Lindsjö Mar 16 '13 at 11:54
  • @Roger.but here we are not adding numbers.you are simply calling add(),sub() methods. – Deepak Mar 16 '13 at 15:25
  • @Deepak I don't know how you are getting the numbers, are they already available? in a stack? Will you ask for them in a gui? I have tried to mimic your original question which asked about the "if" statements. Is your actual question how to build a calculator, or something to parse and evaluate equations? – Roger Lindsjö Mar 17 '13 at 15:40
1

Here you have example of how you can use enums for this. First create your enum

enum MathOperations{
    ADD, SUB, DIV, COS;
}

Then you can use it like this

MathOperations m = MathOperations.valueOf(getCondition().toUpperCase);
switch(m) {
    case ADD: add(); break;
    case SUB: sub(); break;
    //and so on...
}

Of course it will only work if getCondition() will return element that is MathOperations. Otherwise you will get IllegalArgumentException.


You can also try to use Strategy pattern.

Pshemo
  • 122,468
  • 25
  • 185
  • 269
1

You can put add, sub, div, cos… into an ordered list/ array. Then use a for loop to iterate the list. Use break operator and reflection to call appropriate methods.

final String[] OPERATION_LIST = { "add", "sub", "div", "cos" };
String condition = getCondition();
for (String op : OPERATION_LIST) {
    if (condition.equals(op))
        getClass().getMethod(op).invoke(this);
    else
        break;
}

The above for loop equals to your nested if statements. The drawback is other math methods must be public. If not, you need something like Accessing Private Methods.

A note: If you're making a calculator (are you?), maybe Reverse Polish notation is better.

0

According to your code it should always satisfy condition.equals(add) to execute next lines.According to conditions in net lines it never satisfy next condition .When it will come into next lines of code ?.

To check with number of String conditions

You can use switch.

 String condition = getCondition();    
  switch(condition ) {
        case add:
            add();
            break;
        case sub:
            sub();
            break;
        // etc...
    }

Side note:Switch on strings available from Java7.

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307