Aftab
Aftab

Reputation: 2963

How do I convert If statement consisting multiple AND, OR into a switch statement?

I have a piece of code which looks something like this:

     String cStatus = getStatus_c();
     String nStatus = getStatus_n(); 

     if (!((cStatus.equals(PEN) && nStatus.equals(ACT))
            || (cStatus.equals(PEN) && nStatus.equals(SUS))
            || (cStatus.equals(PEN) && nStatus.equals(PEN_CAN))
            || (cStatus.equals(ACT) && nStatus.equals(SUS))
            || (cStatus.equals(ACT) && nStatus.equals(PEN_CAN))
            || (cStatus.equals(SUS) && nStatus.equals(ACT))
            || (cStatus.equals(SUS) && nStatus.equals(PEN_CAN))
            || (cStatus.equals(PEN_CAN) && nStatus.equals(ACT))
            || (cStatus.equals(PEN_CAN) && nStatus.equals(CAN)))) 
{
  //Do someting//
} 

Above code is fulfilling my requirements but I want to change it to some more readable code using anything like switch block etc. I know how switch works but I'm not sure how to covert my existing code.


Just for readability, here is a cleaned-up version (A is PEN, B is ACT, C is SUS and D is PEN_CAN):

if (! (    (cStat == A && nStat == B)
        || (cStat == A && nStat == C)
        || (cStat == A && nStat == D)
        || (cStat == B && nStat == C)
        || (cStat == B && nStat == D)
        || (cStat == C && nStat == B)
        || (cStat == C && nStat == D)
        || (cStat == D && nStat == B)
        || (cStat == D && nStat == D)
      )
)

Upvotes: 2

Views: 149

Answers (5)

davidxxx
davidxxx

Reputation: 131456

Above code is fulfilling my requirements but I want to change it to some more readable code using anything like switch block etc.

A mixing of AND and OR conditional statement cannot be replaced by a single switch case.
You could use embedded switch cases (an outer to handle cStatus and an inner to handle nStatus) but it will really not give a readable code :

boolean isEnabled = true;
switch (cStatus) {

  case PEN:
    switch (nStatus) {
     case ACT:
     case SUS:
     case PEN_CAN:
        isEnabled = false;
    }
    break;
  case ACT:
    switch (cStatus) {
      ...
    }
    break;
}

But you could make your code more readable by eliminating the duplication and by grouping conditional statements with the same cStatus value for example.
You could also use the List.contains() method to check the nStatus value associated to the cStatus value.

Here is a snippet :

List<String> nStatusValueForcStatutPen = Arrays.asList("ACT", "SUS", "PEN_CAN");
List<String> nStatusValueForcStatutAct = Arrays.asList("SUS", "PEN_CAN");
...
if (!((cStatus.equals(PEN) && nStatusValueForcStatutPen.contains(nStatus))
    || (cStatus.equals(ACT) && nStatusValueForcStatutAct.contains(nStatus))
   ...
}

Upvotes: 3

Aftab
Aftab

Reputation: 2963

Below is my final code and I think it's much more readable and clean than the earlier version:

String cStatus = getcStatus();
String nStatus = getnStatus();

String transitionString = cStatus + "_" + nStatus;

  switch (transitionString) {
     case "PEN_ACT":
        break;
     case "PEN_SUS":
        break;
     case "PEN_PENCAN":
        break;
     case "ACT_SUS":
        break;
     case "ACT_PENCAN":
        break;
     case "SUS_ACT":
        break;
     case "SUS_PENCAN":
        break;
     case "PENCAN_AC":
        break;
     case "PENCAN_CAN":
        break;
     default: {
        //DO SOMETHING 
        //In my case throwing an exception i.e. program will not continue further.
     }
  }
  {
  //DO SOMETHING ELSE
  }

Upvotes: 0

souz
souz

Reputation: 101

StatusChange curCange = new StatusChange(CURRENT_STATUS, NEW_STATUS);

if(!ngChange.contains(curChange)){

......do something.....

}

//New codes

class StatusChange{

  final Status cur;

  final Status nw;

  ..override equals method......

}


Set<StatusChange> ngChange=new HashSet();
(
ngChange.add(new StatusChange(PEN,ACT));
ngChange.add(new StatusChange(ACT,PEN));
.........
)

Upvotes: 0

DwB
DwB

Reputation: 38320

The code you have does not require a switch statement. You might consider using a Set

Here is some code:

public class Combination
{
    private final String cStatus;
    private final String nStatus;

    public Combination(
        final String cStatusValue,
        final String nStatusValue)
    {
        cStatus = StringUtils.trimToEmpty(cStatusValue);
        nStatus = StringUtils.trimToEmpty(nStatusValue);
    }

    public int hashCode()
    {
        final int returnValue;

        returnValue = cStatus.hashCode() + nStatus.hashCode();
    }

    public boolean equals(final Object object)
    {
        ... implement equals
    }
}   

... during setup
private Set<Combination> goodCombinationSet = new HashSet<Combination>();

... add all good combinations to the goodCombinationSet.


... when testing.

final Combination testCombination = new Combination(cStatus, nStatus);

if (goodCombinationSet.contains(testCombination))
... do something

Upvotes: 1

Nikolas
Nikolas

Reputation: 44456

I'd suggest you create a diagram to understand clearly the combination of all the conditions.

Firstly you can clearly see that PAN is always the CURRENT_STATUS thus, you can shorten the first condition.

Secondly there are several two-way ocnditions, where certain states could be both NEW_STATUS either CURRENT_STATUS. It's easy to be expressed by the second condition.

Lastly, there are 2 straight one-way conditions (SUS -> PEN_CAN -> CAN) expressed by the last condition.

Combine them together:

boolean penCondition = CURRENT_STATUS.equals(PEN) && 
    (NEW_STATUS.equals(SUS) || NEW_STATUS.equals(PEN_CAN) || NEW_STATUS.equals(ACT));
boolean twoWayCondition = CURRENT_STATUS.equals(ACT) && (NEW_STATUS.equals(SUS) && NEW_STATUS.equals(PEN_CAN)) || 
    NEW_STATUS.equals(ACT) && (CURRENT_STATUS.equals(SUS) && CURRENT_STATUS.equals(PEN_CAN));
boolean oneWayCondition = (CURRENT_STATUS.equals(SUS) && NEW_STATUS.equals(PEN_CAN)) || 
    (CURRENT_STATUS.equals(PEN_CAN) && NEW_STATUS.equals(CAN));

if !(penCondition || twoWayCondition || oneWayCondition) {

}

Upvotes: 1

Related Questions