escutcheon

A Switch on String Idiom for Java

There is no way to perform a true switch on a String in Java. This seemingly trivial bit of functionality is common to many other languages, but has been frustratingly absent (to some) from Java. Various techniques have been offered that involve hashing, Maps, etc., but they are all overly complicated and generally not worth the trouble. With the advent of JDK 5.0 and its implementation of enum, a reasonably close approximation of this can be done using the following idiom. Create an enum using the default integer-based mapping, e.g.:

public enum Day
{
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, 
    THURSDAY, FRIDAY, SATURDAY; 
}

Given this enum, the following switch statement could be used:

switch (Day.valueOf(str))
{
    case SATURDAY:              
    case SUNDAY:
        // weekend processing ...
        break;
    default:
        // weekday processing ...
}

Enum.valueOf() matches the given String to the actual enum name using the same basic hashcode() matching technique that earlier proposals have suggested; but with this idiom, all of that machinery is generated by the compiler and Enum implementation. The set of possible String values is also maintained in a more structured way when held in an enum.

Of course, the above suffers from the serious drawback that Enum.valueof() can throw an unchecked IllegalArgumentException or NullPointerException. The only real way to get around this issue is to create a new static method that absorbs these Exceptions and instead returns some default value:

public enum Day
{
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, 
    THURSDAY, FRIDAY, SATURDAY,
    NOVALUE;

    public static Day toDay(String str)
    {
        try {
            return valueOf(str);
        } 
        catch (Exception ex) {
            return NOVALUE;
        }
    }   
}

Then the switch can be written to include a default clause that handles unexpected String values:

switch (Day.toDay(str))
{
    case SUNDAY:                
    case MONDAY:
    case TUESDAY:
        // etc ...
    default:
        // any non-Day value
}

While not quite as compact as the first technique, this is more robust and offers the possibility of performing case-insensitive switching also by calling, for example, toUpperCase() in the convert method after first checking the passed-in String for null.

» Posted: Friday, December 8, 2006 | Comments (44) | Permanent Link
fleuron

Comments

This was exactly the efficient solution I needed. Much thanks.

» Posted by Jake on March 8, 2007 11:06 PM

Just what I needed, too! Works beautifully.

» Posted by Zephron on March 10, 2007 04:46 PM

Helped a lot! Thanks.

» Posted by Hakan on April 22, 2007 09:23 AM

Excellent! I have been coding in PHP,C# and in my latest project in Java I was very surprised that Java don’t support String switch - this helped, thanks.

» Posted by Q on May 1, 2007 11:10 AM

Too much helpful..thanks buddy ..

» Posted by Anonymous on May 17, 2007 02:40 AM

This is great really, you’ve thought ahead for Chumps like me who would have been bitten later by the Exception.

My only suggestion is to ask if you could make the Sun smile at the top of the page! :-)

» Posted by Chump on June 19, 2007 04:00 PM

Nice and beatifully :)

» Posted by bronyte on June 26, 2007 12:06 PM

great, clear simple and smart !

» Posted by kassad on August 14, 2007 05:35 AM

Great job!! :]
thanks

» Posted by Pedro on September 28, 2007 11:55 PM

Don’t forget to uppercase the string before passing it into valueOf. Otherwise the user would have to enter all commands in uppercase… very Apple ][, but not particularly fun these days. :-)

» Posted by Trejkaz on October 8, 2007 07:46 PM

usefull ! thoose kind of posts are the ones that u wish when googling

» Posted by Lau on October 21, 2007 10:28 AM

This is truly like finding a diamond amongst sackfulls of coal. Thank you for sharing.

» Posted by JohnG on October 31, 2007 12:07 PM

Excellent! I applied this techniques in one of my Java programs today. Thanks

» Posted by pcdinh on December 31, 2007 01:41 PM

How do i use it with Strings like 0F, 0A etc?
I’m very new to java,,was working on C# :)

» Posted by Atul on February 9, 2008 03:41 AM

Should indicate that jdk 1.5 is compulsory. :)
But helpful tip

» Posted by Anonymous on February 15, 2008 11:19 AM

You rock, thanks for this.

» Posted by pd on March 13, 2008 08:33 PM

works
but what about case sensitive strings

» Posted by Anonymous on April 9, 2008 08:08 AM

It is case sensitive by default.

As mentioned in the entry itself, to make it case insensitive, logic would need to be included to ignore the case of the input string.

E.g., replace the try clause with the following so that “Sunday”, “sunday” or “SUNDAY” would all return Day.SUNDAY:

if(str != null)
{
return valueOf(str.toUpperCase());
}
else
{
return NOVALUE;
}
» Posted by winter on April 9, 2008 09:21 AM

Thanks a lot! This saved me much pain looking at all the if-else statements…

» Posted by Michal Filip on April 25, 2008 07:44 AM

After exploring various sites I found the exact solution to my problem here.
Thanks a lot!

» Posted by Himesh on May 19, 2008 02:57 AM

thank you very much!
The method is very good!

» Posted by onroad on June 4, 2008 09:26 AM

Very good. I’ve been programming in java for about 6 years now and i have always stayed away from switch and enums statements for this very limitation. You got to love the programming community. They make my life and job much easier

» Posted by Alao on July 30, 2008 04:40 PM

Thank you very much! Very nice solution

» Posted by Nitek on September 17, 2008 03:14 AM

Hey! Great job. It was the question that was asked in one of the interviews that I faced. Now I got the solution

» Posted by Bhoj Raj on September 30, 2008 03:02 AM

Dude, you rock!

» Posted by ylnotnull on October 28, 2008 02:05 PM

It’s really…..great of use.
Everyone should try……

» Posted by Vijay Raghuvanshi on November 11, 2008 04:45 AM

Thanks you so much for this helpful.

Work as well. ^^,

» Posted by Anonymous on January 3, 2009 09:30 PM

Quite useful! Thanks muchly. :)

» Posted by Anonymous on February 27, 2009 05:21 PM

Fantasic. I too was a little confused to find no select case (or switch) when moving from VB to Java. Life saver!

» Posted by Dan on March 26, 2009 12:24 AM

Interesting with this solution is that you can perform in the ofXxxx also some calculations.

maybe you have a range of values:


public enum Range
{
SMALL, MIDDLE, BIG,
NOVALUE;

public static Range toRange(Integer value)
{
if(value == null){
return NOVALUE;
} else if(value > 100){
return BIG;
} else if(value return SMALL;
} else {
return MIDDLE;
}
}
}


now you can handle also your range

switch (Range.toRange(myvalue))
{
case SMALL:
case MIDDLE:
case BIG:
// etc …
default:
// any non-Range value
}

» Posted by Arno Nyhm on March 27, 2009 12:32 PM

a great help…thanks

» Posted by Sumit on April 27, 2009 02:45 PM

AWESOME! Was just considering writing my own string handler for this and a few other things. One down!

THANKS FOR SHARING :)

» Posted by Angelo on May 18, 2009 08:11 AM

Excellent! Explanation

» Posted by PunnayyaSastryJandhyala on May 18, 2009 10:50 AM

Excellent solution, Exact thing I was looking for

Thanks,
Rohit

» Posted by Rohit on May 28, 2009 09:32 AM

how to convert 0-999 in string pls answer me?

» Posted by kenken on August 15, 2009 09:49 PM

Unfortunately, this suffers from the drawbacks of naming rules for enums. For example, I can’t check to see if something is equal to “set-port” or “—verbose-mode” because enum names cannot have “-” in them. Still a good solution for everything else.
Perhaps an Arraylist with all values stored in in, then an indexOf(String) performed in the switch?
Then you’d have to memorize the order, but it would let you use String literals, I think.

» Posted by Stilenx on October 5, 2009 02:37 AM

thnxs…

r|b|c

» Posted by RBC on October 6, 2009 07:19 AM

Thanks a lot, this is very helpful…. :)

» Posted by Anonymous on November 3, 2009 05:02 AM

This is a beautiful solution !!!

» Posted by Jagadheesan on November 6, 2009 04:32 PM

you saved our life

» Posted by sam&sarah on December 30, 2009 12:35 PM

Excellent tip - thanks!

» Posted by Mick on January 8, 2010 09:42 AM

Wow thanks man - this helped a ton! I hadnt been able to come up with a simpler solution

» Posted by drdan on February 16, 2010 09:38 PM

Note that this isn’t quite the same as switching on a string, as you’re still limited to having enum values which follow the rules of what constitutes a valid identifier. I’m doing a postfix expression calculator where “+” is used to denote addition, “-” subtraction, etc, but doing:

enum Operations
{
+, -, x, /;
}

Obviously does not work. As it stands I do:

switch (opRead.charAt(0))
{
case ‘+’:
….
}

But this has the drawback that if opRead is the string “+dsfkajflaskd” it will be treated like the string “+”. I can add verification code before the switch to ensure the token is only a single character, but then it’s really getting to the point I might as well just do:

if (opRead.equals(“+”))
….

etc.

» Posted by Adam on March 4, 2010 02:45 PM

At any rate, once Java 7 hits all this won’t matter as reports indicate that switches on strings will be added to the language.

http://code.joejag.com/2009/new-language-features-in-java-7/

» Posted by Adam on March 4, 2010 02:56 PM
fleuron

Post a comment