Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Best way to use indexOf with Strings...?

715 views
Skip to first unread message

BCC

unread,
Oct 24, 2001, 1:29:42 PM10/24/01
to
Hi,

I would like to use switch with a list of strings:
switch ( myString ) {
case "a":
case "b":
etc...

Since java switch doesn't support this, I was thinking about making my
list a vector and using indexOf, like this:

myString = "a";
int x = vector.indexOf( myString );

switch ( x ) {
case 0:
case 1:
etc...

Is there a faster way to do this? In this case with vector, I would
have to add each element to the Vector, which is almost as much work as
doing a load of if-else statements.

Ideally, Array would have indexOf, but that doesn't seem to be the case.

What's the standard solution for this?

Thanks,
Bryan

Joe

unread,
Oct 24, 2001, 1:38:45 PM10/24/01
to
BCC <a@b.c> says...

> Hi,
>
> I would like to use switch with a list of strings:
> switch ( myString ) {
> case "a":
> case "b":
> etc...
>
> Since java switch doesn't support this, I was thinking about making my
why not just use if else if statement
if( myString.equals( "a" ) {

} else if ( myString.equals( "b" ) ) {
}
it pretty much the same as a switch statement.
--
Joe

"I bent my wookie" - Ralph Wiggum

Jon Skeet

unread,
Oct 24, 2001, 1:46:20 PM10/24/01
to
BCC <a@b.c> wrote:

A hashtable with String keys and Integer values may well be faster (and
more logical) than this vector approach.

--
Jon Skeet - <sk...@pobox.com>
http://www.pobox.com/~skeet/
If replying to the group, please do not mail me too

Steve Horsley

unread,
Oct 25, 2001, 12:00:06 PM10/25/01
to
Jon Skeet <sk...@pobox.com> wrote in message news:<MPG.16410e648...@mrmog.peramon.com>...

> BCC <a@b.c> wrote:
>
> > I would like to use switch with a list of strings:
> > switch ( myString ) {
> > case "a":
> > case "b":
> > etc...
> >
> > Since java switch doesn't support this, I was thinking about making my
> > list a vector and using indexOf, like this:
> >
> > myString = "a";
> > int x = vector.indexOf( myString );
> >
> > switch ( x ) {
> > case 0:
> > case 1:
> > etc...
> >
> > Is there a faster way to do this? In this case with vector, I would
> > have to add each element to the Vector, which is almost as much work as
> > doing a load of if-else statements.
> >
> > Ideally, Array would have indexOf, but that doesn't seem to be the case.
> >
> > What's the standard solution for this?
>
> A hashtable with String keys and Integer values may well be faster (and
> more logical) than this vector approach.

Agreed. However, this just occured to me:

String color = getTheColorSomehow();
int x = "red green blue".indexOf(color);
switch(x) {
case 0:
...
break;
case 4:
...
break;
case 10:
....
break;
default:
...
}

Urgh!

Steve.

Christopher Archer

unread,
Oct 25, 2001, 7:27:08 PM10/25/01
to
Hi,
Here's a simple class to allow selection based on strings...
public class SwitchCaseStrings
{
private static HashMap tokens = new HashMap();

private final static int _LION = 0;
private final static int _LIONESS = 1;
private final static int _LIONFISH = 2;
private final static int _LIONISE = 3;
private final static int _LIONISED = 4;
private final static int _LIONISER = 5;
private final static int _LIONISES = 6;
private final static int _LIONIZE = 7;
private final static int _LIONIZED = 8;
private final static int _LIONIZER = 9;
private final static int _LIONIZES = 10;
private final static int _LIONLIKE = 11;
private final static int _LIONS = 12;

static
{
addToken("lion", _LION);
addToken("lioness", _LIONESS);
addToken("lionfish", _LIONFISH);
addToken("lionise", _LIONISE);
addToken("lionised", _LIONISED);
addToken("lioniser", _LIONISER);
addToken("lionises", _LIONISES);
addToken("lionize", _LIONIZE);
addToken("lionized", _LIONIZED);
addToken("lionizer", _LIONIZER);
addToken("lionizes", _LIONIZES);
addToken("lionlike", _LIONLIKE);
addToken("lions", _LIONS);
}

private static final void addToken(String token, int value)
{
tokens.put(new String(token), new Integer(value));
tokens.put(new String(token.toUpperCase()), new Integer(value));
}

private final int getToken(String s)
{
Object o = tokens.get(s);
if (o != null)
{
return ((Integer) o).intValue();
}
else
{
return -1;
}
}

public static void main(java.lang.String[] args)
{
SwitchCaseStrings scs = new SwitchCaseStrings();
try
{
System.out.println(scs.testSwitchCaseStrings("lion"));
System.out.println(scs.testSwitchCaseStrings("lioness"));
System.out.println(scs.testSwitchCaseStrings("lionfish"));
System.out.println(scs.testSwitchCaseStrings("lionise"));
System.out.println(scs.testSwitchCaseStrings("lionised"));
System.out.println(scs.testSwitchCaseStrings("lioniser"));
System.out.println(scs.testSwitchCaseStrings("lionises"));
System.out.println(scs.testSwitchCaseStrings("lionize"));
System.out.println(scs.testSwitchCaseStrings("lionized"));
System.out.println(scs.testSwitchCaseStrings("lionizer"));
System.out.println(scs.testSwitchCaseStrings("lionizes"));
System.out.println(scs.testSwitchCaseStrings("lionlike"));
System.out.println(scs.testSwitchCaseStrings("lions"));
System.out.println(scs.testSwitchCaseStrings("other"));
}
catch (Exception e)
{
e.printStackTrace();
}
}

private String testSwitchCaseStrings(String lookFor) throws Exception
{
switch (getToken(lookFor))
{
case _LION :
return "lion";
case _LIONESS :
return "lioness";
case _LIONFISH :
return "lionfish";
case _LIONISE :
return "lionise";
case _LIONISED :
return "lionised";
case _LIONISER :
return "lioniser";
case _LIONISES :
return "lionises";
case _LIONIZE :
return "lionize";
case _LIONIZED :
return "lionized";
case _LIONIZER :
return "lionizer";
case _LIONIZES :
return "lionizes";
case _LIONLIKE :
return "lionlike";
case _LIONS :
return "lions";
default :
throw new Exception("Unknown word \"" + lookFor + "\".");
}
}
}

Chris.

"Steve Horsley" <steve....@cwcom.cwplc.com> wrote in message
news:aa25b022.0110...@posting.google.com...

Jon Skeet

unread,
Oct 26, 2001, 3:33:16 AM10/26/01
to
Christopher Archer <christoph...@wanadoo.fr> wrote:
> private static final void addToken(String token, int value)
> {
> tokens.put(new String(token), new Integer(value));
> tokens.put(new String(token.toUpperCase()), new Integer(value));
> }

Why are you creating new copies of token and token.toUpperCase()? It's
almost certainly unnecessary.

Christopher Archer

unread,
Oct 26, 2001, 7:12:09 PM10/26/01
to
Oops. new is not necessary for the strings here. They're hard-coded
and their memory spaces are already allocated. I now understand
initialization of Strings better.Thanks, Jon.
Therefore, and allowing a leading capital, the code becoms

private static final void addToken(String token, int value)
{
tokens.put(token,
new Integer(value));

tokens.put(token.toUpperCase(),
new Integer(value));

tokens.put(
new StringBuffer(
token.substring(0, 1).toUpperCase()).append(
token.substring(1)),
new Integer(value));
}
Chris.

"Jon Skeet" <sk...@pobox.com> wrote in message

news:MPG.16432217b...@mrmog.peramon.com...

Jon Skeet

unread,
Oct 27, 2001, 3:09:57 AM10/27/01
to
Christopher Archer <christoph...@wanadoo.fr> wrote:
> Oops. new is not necessary for the strings here. They're hard-coded
> and their memory spaces are already allocated. I now understand
> initialization of Strings better.Thanks, Jon.
> Therefore, and allowing a leading capital, the code becoms
> private static final void addToken(String token, int value)
> {
> tokens.put(token,
> new Integer(value));
>
> tokens.put(token.toUpperCase(),
> new Integer(value));
>
> tokens.put(
> new StringBuffer(
> token.substring(0, 1).toUpperCase()).append(
> token.substring(1)),
> new Integer(value));
> }

Okay, next optimisation - just create the Integer instance once.
Also, the fact that you're using a StringBuffer as a key rather than a
String means the above is slightly broken if you want all the keys to be
Strings.

private static final void addToken (String token, int value)
{
Integer v = new Integer (value);

tokens.put (token, v);
tokens.put (token.toUpperCase(), v);
tokens.put (token.substring (0,1).toUpperCase()+
token.substring (1), v);

Christopher Archer

unread,
Oct 27, 2001, 5:55:44 AM10/27/01
to
Of course, then obviously avoid breaking, with this :
new StringBuffer(
token.substring(0, 1).toUpperCase()).append(
token.substring(1)).toString();
Chris.

"Jon Skeet" <sk...@pobox.com> wrote in message

news:MPG.16446e1f9...@mrmog.peramon.com...

Jon Skeet

unread,
Oct 27, 2001, 6:42:28 AM10/27/01
to
Christopher Archer <christoph...@wanadoo.fr> wrote:
> Of course, then obviously avoid breaking, with this :
> new StringBuffer(
> token.substring(0, 1).toUpperCase()).append(
> token.substring(1)).toString();

And what exactly is the point of that? That's what my version does -
just more readably.

There are good reasons to use StringBuffer rather than String
concatenation, but it's important to understand the reasons behind them,
rather than to just assume that all String concatenation is evil. The
way to work this out is to understand what String concatenation does
behind the scenes - and the answer is that it uses a StringBuffer.
However, it uses a StringBuffer for each expression containing
concatenation, which is why:

String x = "hello ";
x += "there ";
x += "Jon";

is less efficient than

StringBuffer xsb = new StringBuffer ("hello");
xsb.append ("there ");
xsb.append ("Jon");

but

String x = "foo "+bar+" baz";

is no better than

String x = new StringBuffer ("foo ").append (bar).append("
baz").toString();

- They're equivalent, but the former is *much* easier to read.

Christopher Archer

unread,
Oct 27, 2001, 7:13:14 AM10/27/01
to
Seems that we still have to decide sometimes between readability and
efficiency...
Chris.

"Jon Skeet" <sk...@pobox.com> wrote in message

news:MPG.16449ff2b...@mrmog.peramon.com...

Jon Skeet

unread,
Oct 27, 2001, 9:04:48 AM10/27/01
to
Christopher Archer <christoph...@wanadoo.fr> wrote:
> Seems that we still have to decide sometimes between readability and
> efficiency...

I think you've missed the point. Using a StringBuffer here doesn't aid
efficiency *or* readability.

Christopher Archer

unread,
Oct 27, 2001, 5:48:09 PM10/27/01
to
Hi,
http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html etc
StringBuffer does sometimes aid efficiency. Why not here too?

Chris.
"Jon Skeet" <sk...@pobox.com> wrote in message
news:MPG.1644c149d...@mrmog.peramon.com...

Jon Skeet

unread,
Oct 28, 2001, 2:08:01 AM10/28/01
to
Christopher Archer <christoph...@wanadoo.fr> wrote:

> http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html etc
> StringBuffer does sometimes aid efficiency. Why not here too?

Read the other posts I've made in this thread in detail - they explain
why StringBuffer can be more efficient, and why that's *not* the case
here.

Christopher Archer

unread,
Oct 28, 2001, 5:22:25 AM10/28/01
to
Based on the bytecode in this context, I've decided to retain StringBuffer.

Chris.
"Jon Skeet" <sk...@pobox.com> wrote in message
news:MPG.1645bf2e6...@mrmog.peramon.com...

Jon Skeet

unread,
Oct 29, 2001, 2:23:33 AM10/29/01
to
Christopher Archer <christoph...@wanadoo.fr> wrote:
> Based on the bytecode in this context, I've decided to retain StringBuffer.

Why? The only difference (which only appears on *some* compilers) is
whether

String x = "foo" + bar;

gets turned into

String x = new StringBuffer ("foo").append (bar).toString();
or
String x = new StringBuffer().append("foo").append(bar).toString();


Now, have you done any performance measurements to see how much
difference in speed you get? I maintain it's going to be insignificant
compared with almost anything else. The difference in readability,
however, *is* significant.

Note that in other cases StringBuffer's efficiency can make *real*
differences - and *those* are the times to use it.

Dale King

unread,
Oct 30, 2001, 10:44:54 AM10/30/01
to
"Jon Skeet" <sk...@pobox.com> wrote in message
news:MPG.16432217b...@mrmog.peramon.com...

> Christopher Archer <christoph...@wanadoo.fr> wrote:
> > private static final void addToken(String token, int value)
> > {
> > tokens.put(new String(token), new Integer(value));
> > tokens.put(new String(token.toUpperCase()), new Integer(value));
> > }
>
> Why are you creating new copies of token and token.toUpperCase()? It's
> almost certainly unnecessary.

Or why not just put the upper case version in the hash table and before
doing the get convert your search key to upper case.

Note however that toUpperCase for this may not be internationalization
friendly. I read an article about this recently, but now can't find it.


Thomas Weidenfeller

unread,
Oct 31, 2001, 4:42:09 AM10/31/01
to
"Dale King" <Ki...@TCE.com> writes:
> Note however that toUpperCase for this may not be internationalization
> friendly. I read an article about this recently, but now can't find it.

You could use toUpperCase(Locale locale), in some cases, but that opens
another can of worms. First, you need to know what Locale to use, and
then you will find out that some conversions are not reversible (the
API documentations lists a few).

E.g.

System.out.println("Straße".toUpperCase(Locale.GERMAN).toLowerCase(Locale.GERMAN));

Other words change their meaning when converted to lowercase. I
recommend the classic German example sentence "Helft den armen Vögeln!"
("Help the poor birds!") :-))).

Depending on the application, you don't want to see that happen.

/Thomas

0 new messages