2

I have an if-else structure in Java as follow:

                    if (A || B || C){
                        if (A){
                            //Do something
                        }
                        if (B){
                            //Do something
                        }
                        if (C){
                            //Do something
                        }
                    } else {
                        //Do something
                    }

I want to know if there is any cleaner and easier way to replace this?

Alex Wang
  • 411
  • 3
  • 16
  • 8
    You do not need the first if statement at all. – SebastianK May 05 '19 at 10:39
  • 4
    @SebastianK how would you do the last `else ` then? `if (! (A || B || C))` ? – Bart Friederichs May 05 '19 at 10:40
  • With a default and switch... see below – Jay May 05 '19 at 10:41
  • 2
    Could you give some more information about the use-case here? How are `A`, `B` and `C` evaluated? Are they expected to be mutually exclusive (i.e. at most one of them is set)? There are multiple ways to do _exactly_ what you've got here put below, but depending where the variables come from there might be more readable ways (lookup from `Map`, array of callbacks, etc.). – BeUndead May 05 '19 at 10:55
  • @Alex Wang it would also be useful to know 1) If the `A`, `B` and `C` are exclusive (only one can be true) and 2) if "Do something" is always the same piece of code. – Dorian Gray May 05 '19 at 11:03
  • @Dorian Gray Hi in my case A, B and C are independent on each other and "Do something" is not the same under different conditions – Alex Wang May 05 '19 at 11:09

5 Answers5

5

If A,B and C are conditions which are expensive to evaluate, you could use an additional flag to make sure they are only evaluated once:

boolean found = false;
if (A) {
    //Do something
    found = true;
}
if (B){
    //Do something
    found = true;
}
if (C){
    //Do something
    found = true;
}
if (!found) {
    //Do something
}

Otherwise (i.e. if they are not expensive to evaluate), I'd keep your current conditions.

Bart Friederichs
  • 33,050
  • 15
  • 95
  • 195
Eran
  • 387,369
  • 54
  • 702
  • 768
  • 3
    Thanks I think this can reduce the time complexity because in my case, A, B, C are some complexed conditions – Alex Wang May 05 '19 at 10:53
  • As a matter of personal preference, I would put `found = true;` first in the conditionals, in order that it's easy to see that you are setting the flag. – Andy Turner May 05 '19 at 12:42
2

Yes.

if (A) {
  // do A
}
if (B) {
  // do B
}
if (C) {
  // do C
}
if (! (A || B || C)) {
  // do "neither A or B or C"
}
Bart Friederichs
  • 33,050
  • 15
  • 95
  • 195
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/192860/discussion-on-answer-by-bart-friederichs-is-there-any-cleaner-way-to-write-multi). – Jean-François Fabre May 05 '19 at 12:12
1

Whilst I think what you have is fine, you could do it like this:

boolean d = false;
if (d |= A) { ... }
if (d |= B) { ... }
if (d |= C) { ... }
if (!d) {
  // What to do if A..C are all false.
}

This will set d to true if any of the conditions are matched (d is for "did something").

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
1

Just one more possible solution:

public class ABC {

    private static final Logger log = LoggerFactory.getLogger(ABC.class);

    @Test
    public void abc() {
        boolean A = true;
        boolean B = false;
        boolean C = true;

        boolean abcProcessed = false;

        abcProcessed |= process(A, () -> {
            // Do something for A
            log.debug("A");
        });
        abcProcessed |= process(B, () -> {
            // Do something for B
            log.debug("B");
        });
        abcProcessed |= process(C, () -> {
            // Do something for B
            log.debug("C");
        });

        if (!abcProcessed) {
            // Do something for !(A||B||C)
            log.debug("!(A||B||C)");
        }
    }

    private boolean process(boolean flag, DoSomethingInterface doSomethingInterface) {
        // check condition
        if (flag) {
            // execute code specific for condition
            doSomethingInterface.doSomething();
            // return true (processed)
            return true;
        }

        // return false (not processed)
        return false;
    }

    public interface DoSomethingInterface {

        // code specific for condition
        void doSomething();
    }
}

An idea is to move condition checking and related code to separate method.

Bor Laze
  • 2,458
  • 12
  • 20
0

I think you should use else if conditions:

if(A){

}else if(B){

}else if(C){

}else if(D){

}

But, if you have many conditions like A,B,C etc it feels that something wrong with logic of your program

Nikita
  • 94
  • 1
  • 3
  • 1
    No, you cannot use it, as there might be `A = true, B = true, C = false`, Your code will also execute the first case then. That's not the same as in the original post. – Dorian Gray May 05 '19 at 12:00