7

I need suggestion for the right approach to apply conditions in Java.

I have 100 conditions based on which I have to change value of a String variable that would be displayed to the user.

an example condition: a<5 && (b>0 && c>8) && d>9 || x!=4

More conditions are there but variables are the same more or less.

I am doing this right now:

    if(condition1)
    else if(condition2)
    else if(condition3)
    ...

A switch case alternative would obviously be there nested within if-else's i.e.

if(condition1)
 switch(x)
  {
   case y:
     blah-blah
   }        
else if(condition2)
switch(x)
  {
   case y:
     blah-blah
   }  
else if(condition3)
...

But I am looking for some more elegant solution like using an Interface for this with polymorphic support , What could be the thing that I could possibly do to avoid lines of code or what should be the right approach.

---Edit---


enter image description here

I actualy require this on an android device. But its more of a java construct here.

This is a small snapshot of conditions that I have with me. More will be added if a few pass/fail. That obviously would require more if-else's with/without nesting. In that case would the processing go slow.

I am as of now storing the messages in a separate class with various string variables those I have kept static so if a condition gets true then I pick the static variable from the only class and display that one. Would that be right about storing the resultant messages.

Prateek
  • 3,923
  • 6
  • 41
  • 79
  • 4
    I am not sure about avoiding lines of code. But to increase performance , placing more frequent cases in top? – Bharath Mg Jan 09 '13 at 13:46
  • 1
    IMHO this question more suitable for http://codereview.stackexchange.com/ – Slava Semushin Jan 09 '13 at 13:46
  • 4
    how important is performance for you? because some of the more "elegant" solutions in terms of flexibility and readability will performa worse than an ugly tree if if-elses – radai Jan 09 '13 at 13:47
  • 2
    It seems to me that you have way too many conditions. I think that your design should be improved, please add some details about the high level task you want to accomplish with that code – mariosangiorgio Jan 09 '13 at 13:50
  • @radai Performance is like always very important to me, you are right it would degrade by avoiding if-elses. – Prateek Jan 09 '13 at 14:01
  • 1
    pKs - then that throws any classification/rule engine out the window. the lookup table suggested by @thkala below is your best option then and it might actually perform faster, depending on how fast you can generate the key given the input data – radai Jan 09 '13 at 14:03
  • Flagged as duplicate of http://stackoverflow.com/questions/1199646/long-list-of-if-statements-in-java - such a very similar question has been asked shortly - http://stackoverflow.com/questions/14136721/converting-many-if-else-statements-to-a-cleaner-approach – SpaceTrucker Jan 09 '13 at 14:12
  • @pKs Why should performance be considered, if these conditions are used for user interactions, which are naturally a very slow kind of IO? – SpaceTrucker Jan 09 '13 at 14:55
  • @SpaceTrucker This actually is a situation where I have to refresh a UI element based on the condition fulfillment. More the time takes to check and traversal within the if else or whatever use case. – Prateek Jan 09 '13 at 17:42

4 Answers4

7

Depending on the number of conditional inputs, you might be able to use a look-up table, or even a HashMap, by encoding all inputs or even some relatively simple complex conditions in a single value:

int key = 0;

key |= a?(1):0;
key |= b?(1<<1):0;
key |= (c.size() > 1)?(1<<2):0;
...

String result = table[key]; // Or result = map.get(key);

This paradigm has the added advantage of constant time (O(1)) complexity, which may be important in some occasions. Depending on the complexity of the conditions, you might even have fewer branches in the code-path on average, as opposed to full-blown if-then-else spaghetti code, which might lead to performance improvements.

We might be able to help you more if you added more context to your question. Where are the condition inputs coming from? What are they like?

And the more important question: What is the actual problem that you are trying to solve?

thkala
  • 84,049
  • 23
  • 157
  • 201
  • 1
    I think that this is going to be hard to maintain, because you end up with a long sequence of statements, where a single statement itself is complex. As these conditions are used for user messages they might be subject to change quite often. So you will create a maintenance hotspot in your code. – SpaceTrucker Jan 09 '13 at 14:53
  • @SpaceTrucker: I agree in principle, although that would depend on how the code is actually laid out and what exactly it is being used for. It is quite probable that, once the OP lets us know what exactly this is all about, we will find a more elegant solution to tackle the high-level task, rather than trying to essentially answer the question of "How can one code a complex logic table in Java?" – thkala Jan 09 '13 at 16:03
  • @thkala Sorry for my late reply and thanks for your suggestion. The message that I want to display is fixed. But as you have suggested the lookup table , I am going to consider the same for it. But what If I were just using if-elses , where would I actualy lag. – Prateek Jan 09 '13 at 17:45
  • @thkala Though my question has been closed and I have accepted your answer, I still need a suggestion regarding creating a class full of public static string messages. Shall I do this or not? – Prateek Jan 10 '13 at 06:31
  • @thkala It is great in principle, but I'm not sure how you can apply it to the specific question, where there are possibly more than 32 a, b, c... conditions. And I agree with other comments that this can quickly become a mess. – assylias Jan 10 '13 at 08:08
  • 1
    @pKs: It depends... that would indeed separate the strings from the rest of your code, but it does present a few modularity issues. Do you really want to have all classes in your application pull their strings from there? If I were you I would first have a look at how Android applications support internationalization - chances are that you will have to do that at some point anyway, so why not do it properly from the beginning? – thkala Jan 10 '13 at 08:57
  • 2
    @assylias: I don't know about "great", but it can be a good choice in *some* cases. As to your concern about `int`, size matters not - you can always use a `long` or even a `BitSet`. As for it becoming a mess, a suitable coding style can help a lot - e.g. using constants for the bit masks. – thkala Jan 10 '13 at 08:58
4

There are a lot of possibilities to this. Without knowing much about your domain, I would create something like (you can think of better names :P)

 public interface UserFriendlyMessageBuilder {
      boolean meetCondition(FooObjectWithArguments args);

      String transform(String rawMessage);
 }

In this way, you can create a Set of UserFriendlyMessageBuilder and just iterate through them for the first that meets the condition to transform your raw message.

public class MessageProcessor {
    private final Set<UserFriendlyMessageBuilder> messageBuilders;

    public MessageProcessor(Set<UserFriendlyMessageBuilder> messageBuilders) {
        this.messageBuilders = messageBuilders;
    }

    public String get(FooWithArguments args, String rawMsg) {

        for (UserFriendlyMessageBuilder msgBuilder : messageBuilders) {
            if (msgBuilder.meetCondition(args)) {
                return msgBuilder.transform(rawMsg);
            }
        }
        return rawMsg;    
    }
}
Caesar Ralf
  • 2,203
  • 1
  • 18
  • 36
  • that would have an O(N) lookup time (N is the number of such classifiers) as opposed to probbaly a lower complexity for an if-else tree (log(N) ideally for the tree) – radai Jan 09 '13 at 14:11
  • 2
    @radai I see your point. ~Log(N) would only happens if his if/elses where nested inside another if/elses. If not, they will be the same O(N) also. Besides, I think that for this case of simple comparissions, the time spent will be really low. – Caesar Ralf Jan 09 '13 at 14:16
  • @RalfHoppen The if-elses are not nested in my case but It could be a matter of choice. Lets also mark it to add suggestion on weather I go with nesting or not – Prateek Jan 09 '13 at 17:47
0

What it seems to me is "You have given very less importance to design the product in modules" Which is the main factor of using OOP Language.

eg:If you have 100 conditions and you are able to make 4 modules then therotically for anything to choose you need 26 conditions.

Saty
  • 1,068
  • 11
  • 24
0

This is an additional possibility that may be worth considering.

Take each comparison, and calculate its truth, then look the resulting boolean[] up in a truth table. There is a lot of existing work on simplifying truth tables that you could apply. I have a truth table simplification applet I wrote many years ago. You may find its source code useful.

The cost of this is doing all the comparisons, or at least the ones that are needed to evaluate the expression using the simplified truth table. The advantage is an organized system for managing a complicated combination of conditions.

Even if you do not use a truth table directly in the code, consider writing and simplifyin one as a way of organizing your code.

Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75