ecthelion84
ecthelion84

Reputation: 356

If/Else alternative

public boolean typeMatch(char c1, char c2) {

    if (c1 == '{' || c1 == '}') {
        return (c2 == '{' || c2 == '}');
    } else if (c1 == '(' || c1 == ')') {
        return (c2 == '(' || c2 == ')');
    } else if (c1 == '[' || c1 == ']') {
        return (c2 == '[' || c2 == ']');
    } else {
        return false;
    }
}

I have the above code in my program and I was wondering if there is a better way to implement this method without using a lot of if/else statements.

Upvotes: 2

Views: 229

Answers (5)

Ted Hopp
Ted Hopp

Reputation: 234857

Elliott's solution is going to be much better than mine, but I thought I'd have some fun.

private static final Map<Character, Set<Character>> pairMap;

public boolean typeMatch(char c1, char c2) {
    Set<Character> s = pairMap.get(c1);
    return s != null && s.contains(c2);
}

static {
    pairMap = new HashMap<>();
    register(makeSet('{', '}'));
    register(makeSet('(', ')'));
    register(makeSet('[', ']'));
}

private static Set<Character> makeSet(char... chars) {
    Set<Character> s = new HashSet<>(chars.length, 1.0f);
    for (char c : chars) {
        s.add(c);
    }
    return s;
}

private static void register(Set<Character> s) {
    for (Character c : s) {
        pairMap.put(c, s);
    }
}

The memory requirements for this solution are gross. The only thing it has to recommend it is that it will scale better in terms of execution time if you need to handle a very large number of character equivalence classes instead of the three pairs. Plus it can be generalized to handle other types besides char (or, to be accurate, Character).

Upvotes: 3

GreyBeardedGeek
GreyBeardedGeek

Reputation: 30088

There's already an accepted answer here, and it's a good one, but it's very specific to the problem at hand.

For folks who got here by searching for a more generic solution, I'd like to offer my favorite pattern for doing away with if/else chains:

boolean result = false;
do {
   if(condition1) {
      result = true;
      break;
   }

   if(condition2) {
     break;
   }

   // etc.

} while(false);

return result;

This, of course, is generalizable to any return type.

Upvotes: 0

Elliott Frisch
Elliott Frisch

Reputation: 201537

Pairs of Characters in an Array of Char Array(s)

You could extract your symbol pairs (open and close) into a char[][], and then loop through that array to test for matches. Something like,

static final char[][] pairs = { { '{', '}' }, { '(', ')' }, { '[', ']' } };

public boolean typeMatch(char c1, char c2) {
    for (char[] pair : pairs) {
        if (c1 == pair[0] || c1 == pair[1]) {
            return c2 == pair[0] || c2 == pair[1];
        }
    }
    return false;
}

Pairs of Characters in an Array of String(s)

Alternatively, it may be easier to read1 if we implement that with String(s) and String.indexOf(int)2. Something like,

public boolean typeMatch(char c1, char c2) {
    String[] pairs = { "{}", "()", "[]" };
    for (String pair : pairs) {
        if (pair.indexOf(c1) != -1) {
            return pair.indexOf(c2) != -1;
        }
    }
    return false;
}

1And that's never a bad thing.
2The linked Javadoc says, in part, In either case, if no such character occurs in this string, then -1 is returned.

Upvotes: 5

ajb
ajb

Reputation: 31699

private static final String PAIRS = "{}()[]";
public boolean typeMatch(char c1, char c2) {
    int indexOfC1 = PAIRS.indexOf(c1);
    int indexOfC2 = PAIRS.indexOf(c2);
    return indexOfC1 >= 0 && indexOfC2 >= 0 && (indexOfC1 / 2 == indexOfC2 / 2);   
}

A bit on the tricky side, perhaps...

Upvotes: 1

ug_
ug_

Reputation: 11440

Not the most readable but I was having some fun with trying to do this with bit wise operators and I figured I would post it

public boolean typeMatch(char c1, char c2) {
    int xor = c1 ^ c2;
    if(xor == 6) { // 2 apart
        return c1 == '{' || c1 == '}' || c1 == '[' || c1 == ']';
    } else if(xor == 1) { // 1 apart
        return c1 == '(' || c1 == ')';
    } else if(xor == 0) { // same
        return c1 == '(' || c1 == ')' || 
                c1 == '{' || c1 == '}' || c1 == '[' || c1 == ']';
    }
    return false;
}

It should be quite fast at least...

Upvotes: 0

Related Questions