This week's giveaway is in the Android forum.
We're giving away four copies of Android Security Essentials Live Lessons and have Godfrey Nolan on-line!
See this thread for details.
The moose likes Java in General and the fly likes Avoding multiple ifs Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Avoding multiple ifs" Watch "Avoding multiple ifs" New topic
Author

Avoding multiple ifs

Amit A. Patil
Ranch Hand

Joined: May 04, 2006
Posts: 38
I have a function to which a String is passed
rawStr="BallRed0550"
which mean ball is red of quantity 5 and weight 50 grams.
i do certain processing based on this string,
if("Blue".equals(rawStr.subString(0,4))){

do something...
}else("Red".equals(rawStr.subString(0,4))){
do something
}else {
do something...
}
Someone suggested using a hasMap will be faster..i mean hashmap of objects with keys as "Blue" ,"Red" and calling method of that object .Is it true?
What is the fasted way of doing this?
Anupam Sinha
Ranch Hand

Joined: Apr 13, 2003
Posts: 1088
I would suggest having constants to define the colour and then if weights are predefined use constants for them as well. Parsing a String doesn't sound right. Secondly how do you determine if the colour of the ball is RED or BLUE with substring?
Amit A. Patil
Ranch Hand

Joined: May 04, 2006
Posts: 38
I have no control this string is sent by a leagacy system cant change it
Peter Chase
Ranch Hand

Joined: Oct 30, 2001
Posts: 1970
OK, so you can't change the String coming from the legacy system, but you can parse it just once and convert it to something that can be better used in the rest of your program. Repeatedly substringing and doing string comparisons is ugly and inefficient.

I would suggest a static hash map with keys that are the colours, and values that are objects of an appropriate type. Perhaps define an enum type for the colours.

If you use a hash map, use consistent case (e.g. lower case) for the keys, then convert all incoming strings to that case. That's assuming that the case in the incoming strings is not significant, of course.


Betty Rubble? Well, I would go with Betty... but I'd be thinking of Wilma.
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
Re the HashMap idea: refactoring a switch case or if-else into a Strategy is a neat option.

What's really neat is that you can close this code for future modification and add new colors and strategies through the creator method, getStrategyFor(). If I expected lots of change I might move that to a factory-like class and set it up from configuration so I could add new colors and behaviors without touching this class ever again.


A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Amit A. Patil
Ranch Hand

Joined: May 04, 2006
Posts: 38
I did a quick check HashMap is always faster
package test.server;

import java.util.HashMap;

public class TestIfs {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int count=0;
for(int i=0;i<10000;i++){
if(multipleifs()> multipleMap()){
count++;
}
}
System.out.println("Ifs were slower "+count +"out of 10000");

}

public static long multipleifs() {
String s="Red";long avg=0;
for(int i=0;i<10000;i++){
long prev=System.nanoTime();
if("Black".equals(s)){

}else if("Green".equals(s)){

}else if("Grey".equals(s)){

}else if("White".equals(s)){

}else if("Red".equals(s)){

}
avg+=System.nanoTime()-prev;
}
// System.out.println(avg/10000.0);
return avg;
}

public static long multipleMap(){
HashMap map=new HashMap();long avg=0;
map.put("Red","Red");
map.put("Black","Black");
map.put("Green","Green");
map.put("White","White");
map.put("Grey","Grey");
for(int i=0;i<10000;i++){
long prev=System.nanoTime();
map.get("Green");
avg+=System.nanoTime()-prev;
}
// System.out.println(avg/10000.0);
return avg;
}

}
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
I'm a little surprised at the result, but then again you loaded the dice by always looking for "red" which is at the end of the if-else chain. The longer the chain gets the more effect something like that might have.

I almost always make choices like this based on what improves the design - hence my emphasis on Bertand Meyers' "open closed" aspect of the map loaded from configuration - and almost never on performance.

Then again, I rewrote (not refactored) a complex utility class this year and made it several times faster more or less by accident. Sometimes better is just better.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
One problem with your initial code is how to extract the "Red" or "Blue" from the initial string. such as "BallRed0550". Note that rawStr.subString(0,4) extracts the first four characters of rawStr - which is the word "Ball", typically. You could use substring(4, 7) to get "Red" - but if it's "BallBlue0123" then you need substring(4, 8). The HashMap approach will only work if you can extract the exact string in advance. Perhaps you can do this with regular expressions:

This assumes that the color is always preceded by "Ball" and followed by a number. If that's not the case, you will need to know more about what types of rawStr are possible here.

Note that one advantage of the original chain of ifs is that you have much more flexibility in what you test on each line. You don't have to use .equals() only. For example you could say
Now I do generally recommend the HashMap approach for this sort of thing whenever possible. But sometimes it just doesn't work, and a chain of if statements is what you need.


"I'm not back." - Bill Harding, Twister
 
 
subject: Avoding multiple ifs
 
Similar Threads
.getSelection()
Two bucket puzzle
Enum Question
How to assign names to buttons and tell which button was pressed in the Action class?
Jtree problem