PFranchise
PFranchise

Reputation: 6762

Improve Java code: too many if's

I have several cases and I am just using simple if ... if else blocks.

How can I reduce the number of if statements in this code?

Perhaps I could use a lookup table, but I am not sure how to implement it in Java.

private int transition(char current, int state)
{
    if(state == 0)
    {
        if(current == 'b')
        {
            return 1;
        }
        else 
            return 0;
    }
    if(state == 1)
    {
        if(current == 'a')
        {
            return 2;
        }
        else 
            return 0;
    }
    if(state == 2)
    {
        if(current == 's')
        {
            return 3;
        }
        else 
            return 0;
    }
    if(state == 3)
    {
        if(current == 'e')
        {
            return 3;
        }
        if(current == 'b')
        {
            return 4;
        }
        else 
            return 0;
    }
    if(state == 4)
    {
        if(current == 'a')
        {
            return 5;
        }
        else 
            return 0;
    }
    if(state == 5)
    {
        if(current == 'l')
        {
            return 6;
        }
        else 
            return 0;
    }
    else
        return 0;
}

Upvotes: 12

Views: 2545

Answers (7)

RobertPitt
RobertPitt

Reputation: 57268

i switch statement would be best here:

private int transition(char current, int state)
{
    switch(state)
    {
        case 0:
            return current == 'b' ? 1 : 0;
        case 1:
            return current == 'a' ? 2 : 0;
        case 2:
            return current == 's' ? 3 : 0;
        case 3:
            return current == 'e' ? 3 : (current == 'b' ? 4 : 0);
        case 4:
            return current == 'a' ? 5 : 0;
        case 5:
            return current == 'l' ? 6 : 0;
        default:
            return 0;
    }
}

And a note, theres only 5 if statements there checking pure intergers, this is not exactly an overhead.

Upvotes: 6

casablanca
casablanca

Reputation: 70731

What you're trying to do looks very much like a finite state machine, and these are usually implemented with the help of a transition table. Once you set up the table, it's simply a matter of indexing to the position you want to get the return value. Assuming your return values are all less than 256, you can use a 2D byte array:

byte table[][] = new byte[NUM_STATES][NUM_CHARACTERS];
// Populate the non-zero entries of the table
table[0]['b'] = 1;
table[1]['a'] = 2;
// etc...

private int transition(char current, int state) {
  return table[state][current];
}

Upvotes: 32

duduamar
duduamar

Reputation: 3924

If this code is about to be expanded over the time, why not use a state machine? Each state will return the next state based on the character it receives. Maybe it's an overkill for this code, but it'll be a lot easier to maintain, expand & read.

Upvotes: 5

duffymo
duffymo

Reputation: 308998

Looks like you need a better abstraction for a finite state machine. Think about a class that encapsulates what you want in a better way so you can extend it by configuration rather than modifying code.

Upvotes: 5

Nikita Rybak
Nikita Rybak

Reputation: 68026

Well, you can easily utilize hash. Simple and clean.

    // declare hashtable
    Map<String, Integer> map = new HashMap<String, Integer>();
    map.put("0-b", 1);
    map.put("1-a", 2);
    map.put("2-s", 3);
    ...

    // get result
    Integer result = map.get(state + "-" + current);
    // change null (nothing found) to zero
    return result == null ? 0 : result;

Upvotes: 14

Oblomov
Oblomov

Reputation: 769

Use switch statement for the outer if chain:

switch (state) {
  case 0: <code> ; break;
  case 1: <code> ; break;
  case 2: <code> ; break;
  <etc>
  default: return 0; break;
}

Upvotes: 2

Jason S
Jason S

Reputation: 189856

consider interfaces + enums:

interface State<T>
{
    public void State<T> step(T input);
}

enum MyState implements State<Character> {
    STATE0(0) { @Override public void MyState step(Character c) { return c == 'b' ? STATE1 : STATE0; }},
    STATE1(1) { @Override public void MyState step(Character c) { return c == 'a' ? STATE2 : STATE0; }},

    /* rest of states here */

    final private int value;
    MyState(int value) { this.value = value; }
    public int getValue() { return this.value; }
}

class SomeClass
{
   public MyState currentState = STATE0;

   public void step(char input)
   {
      this.currentState = this.currentState.step(input);
   }
}

Upvotes: 9

Related Questions