3

Extending this question, I have accepted an answer which says use lookup table or hashmap for this case as it would be a better construct to handle multiple conditions.

Current construct.

Class to store messages.

    public class ProgressMessages 
    {
     public static String msg1="Welcome here .....";
     .
     .
     .
     //around 100 more similar static variables.
    }

Condition and Display the proper message from the above class.

    int x=calculatedVal1(m,n); 
    int y=calculatedVal2(o,q);

    SimpleDateFormat formater=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date d=new Date();
    String s=formater.format(d);

    try {
          long d1 = formater.parse("2013-01-10 13:53:01").getTime();
          long d2=formater.parse(s).getTime();
          totaldays=Math.abs((d1-d2)/(1000*60*60*24));
         } catch (ParseException e) {
            e.printStackTrace();
         }

    if(totaldays<7&&x<20)
     {
      System.out.println("my message...1"+ProgressMessages.msg1); 
     }

    else if(totaldays<7&&x>10&&y<20)
    {
      System.out.println("my message...2"+ProgressMessages.msg2);
    }   
    ....
    //obvioulsy 100 more else-if's to display 100 messages.

I actually would like to know how would a look-up table help in this case?

How should it be implemented in java Hashmap/Hashtable etc, What would be advantageous how?

----Edit---

I am going by @assylias anwer as it is more clean to apply . But If I use Enums then I have got a fix.

To describe the big picture...

i.e. List of messages is like...

1) "Welcome," + nameOfUser+"your success rate is"+ succssRate +"%"+ earlier it was +earlier +"%".

2) "Oh yes.."+ succssRate +"%"+ improved from +earlier +"%".

3.) "Now you should focus on "+exerCiseName.

How could I do this using Enumeration as it has fixed String data. Could I make different constructors? How any example with the edit code to assylas answer?

Community
  • 1
  • 1
Prateek
  • 3,923
  • 6
  • 41
  • 79
  • That's basically all in the [answer you accepted](http://stackoverflow.com/a/14236753/1749753). The advantage would be that is faster than your if/else tree because you could just calculate the index from your condition and do the lookup in constant time. The easiest way to implement it would be a simple `String[]`. – jlordo Jan 10 '13 at 07:42
  • @jlordo How could I remember the index of variable in a String[] but it would be more semantic to use variable names with proper meanings, that's why I am not using a String[] here. So again how do I implement this in code , Can you modify it or explain in further. – Prateek Jan 10 '13 at 07:51
  • Look at the [other answer](http://stackoverflow.com/a/14236753/1749753). You use your conditions to calculate the index, and then use the message stored at that index. That's a clean approach, works in constant time and avoids a big if then else mess. – jlordo Jan 10 '13 at 07:51
  • @jlordo I don't think it is that easy to implement. In particular, there are possibly more than 32 different conditions so using a 32 bit key + bit shifting would not be able to account for all possible combinations. – assylias Jan 10 '13 at 08:05
  • @assylias: I am also not a fan of the bit shifting, but using `int` still gives him over 2 billion possible indexes (Calculating the right index would be a bit more complicated then). I am also convinced that we are dealing with a XY Problem here. – jlordo Jan 10 '13 at 08:13
  • @jlordo of course an int can hold 2bn conditions (4bn actually), but the way it is constructed in the answer to the other question, you can't have more than 32 individual conditions because it is used as a bitset. – assylias Jan 10 '13 at 08:15
  • @jlordo XY problem? Could I make a table structure and could look up into that table structure in java? – Prateek Jan 10 '13 at 08:16
  • @pKs [XY Problem](http://mywiki.wooledge.org/XyProblem) - although your other question has additional context. – assylias Jan 10 '13 at 08:17
  • @assylias I guess I am not even close to the answer , what is he trying to do could you explain in simple terms. – Prateek Jan 10 '13 at 08:17
  • @pKs: I think you can't get any closer to an answer, especially after what [assylias](http://stackoverflow.com/a/14253093/1749753) posted under this question. I thought you knew what a [XY Problem](http://mywiki.wooledge.org/XyProblem) is, since there is a link to it in the [answer you accepted in your previous question](http://stackoverflow.com/a/14236753/1749753). – jlordo Jan 10 '13 at 08:27
  • @jlordo No i didn't. As a bottom line and not extending this further could you just say that what has posted is better approach then what I am doing right now. – Prateek Jan 10 '13 at 08:31
  • @pKs: What you posted would work, but IMHO is horrible and extremely difficult to debug code. The answer here is a really good approach (easy to maintain, runtime ok). Personally, I'd go with a lookup table. Before coding any of it, I would think about the problem again, and if you come to the conclusion that we're talking about the Y in XY Problem here, I would write another question asking how to solve the X problem ;) – jlordo Jan 10 '13 at 08:45
  • @jlordo :P you are true. But lets accept this answer but my requirement is that message would also have some variables added like i.e Welcome, 'name of user' which would change obviously. How will I manage this if I go with this code. – Prateek Jan 10 '13 at 08:49
  • 2
    @pKs: Now I'm sure we're talking about Y :) Here's another good description: [What is the XY problem?](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) . You can put variables in your strings and use `String.format()`. But why do you have 100+ conditions for a welcome message??? We could probably lead you to a much better solution when you would describe to us, what it is you are trying to do (big picture). – jlordo Jan 10 '13 at 08:53
  • @pKs: forget about the `String.format()` wouldn't work nice with this answer, neither with a lookup table, only with your approach. Try to ask a new question, and describe the X problem. Feel free to give me an @ reply here, linking to your new question, so I won't miss it. – jlordo Jan 10 '13 at 09:03
  • When and how are those messages shown? I would use different classes for `WelcomeMessage`, `ImprovementMessage`, `NextExcersiceMessage` and so on... – jlordo Jan 10 '13 at 09:21
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/22506/discussion-between-pks-and-jlordo) – Prateek Jan 10 '13 at 09:23

3 Answers3

3

You could use an enum, assuming the list of messages is known at compile time. The advantages are that each message is now responsible for holding its condition, and the calling code will be much simpler.

public enum Message {

    MESSAGE1("Welcome") {
        @Override
        boolean isApplicable(long totalDays, int x, int y) {
            return totalDays < 7 && x < 20;
        }
    },
    MESSAGE2("Bye bye") {
        @Override
        boolean isApplicable(long totalDays, int x, int y) {
            return totalDays < 7 && x > 10 && y < 20;
        }
    };

    private String msg;

    Message(String msg) {
        this.msg = msg;
    }

    abstract boolean isApplicable(long totalDays, int x, int y);

    public static String lookupMessage(long totalDays, int x, int y) {
        for (Message m : Message.values()) {
            if (m.isApplicable(totalDays, x, y)) {
                return m.msg;
            }
        }
        throw new IllegalArgumentException();
    }
}

Now in your calling code, no more if / else if, just one line of code:

System.out.println(Message.lookupMessage(1, 2, 3));

Note 1: This is not as efficient as using a Map as the lookup is an O(n) operation, but because n is 100 or so it should not be a significant performance penalty. And it is more readable and maintainable than the solution proposed in the other answer.

Note 2: You could even put the conditions / messages in a flat file, read the file at runtime and use a scripting engine to eval each condition at runtime. It would be slightly slower (but we are talking about sub-milliseconds here) but would remove all the clutter from your code and put it in a configuration file.

assylias
  • 321,522
  • 82
  • 660
  • 783
  • Is your approach better then what I am doing right now in my question? – Prateek Jan 10 '13 at 08:20
  • Guess that's clean and cool can you suggest how could I add some data in the message i.e. Welcome + nameOfUser if I go by this approach. – Prateek Jan 10 '13 at 08:43
  • @pKs better depends on your criteria. Performance wise it is similar. It looks cleaner too. Once you have the "Welcome" part you can concatenate whatever you want, like a username... – assylias Jan 10 '13 at 09:02
2

I would use a

Map<Criteria, Message> lookupTable;

where Criteria is a class you write (and override equals() and hashCode()), representing the criteria to choose a message.

Message is also a class you write, which encapsulates the actual message String but also provides you some functionality to set the variables.

With this solution you have to initialize the map once at the beginning of your program and can always use it like this:

Criteria criteria = ... // gather your criteria somehow
Message msg = lookupTable.getMessage(criteria);
// use your variable setting methods here
String message = msg.toString();
jlordo
  • 37,490
  • 6
  • 58
  • 83
0

If you have so many conditions, you cant avoid putting those conditions some where in the code. The advantages of using lookup table is 1)Easy to implement. 2)Flexible.If you want to change the value of some message in future, you can go to looktable class and change.

Renjith
  • 3,274
  • 19
  • 39
  • How do you use a map in that context? – assylias Jan 10 '13 at 07:41
  • I am ok with the conditions as they are to be implemented in the code itself but what do you think making a class and storing the variables as static would be the right thing , how could I do this with a look up table in the java-end itself. – Prateek Jan 10 '13 at 07:42
  • Making a class and storing variables as static would be the right approach.That is how you can implement a look up table. – Renjith Jan 10 '13 at 07:47
  • @assylias I am not sure about this but as to index between the conditions I need some explained way of implementation as I have mentioned In my question that answer I accepted is saying something. – Prateek Jan 10 '13 at 07:49