Java – Caveats of using String.hashCode() on a switch on java < 1.7

designjavaswitch statement

There are several cases when I want to switch over a String input. I decided for implementing something like:

public Object doStuff(String param) {
    switch (param.hashCode()) {
    case 1234546:
         break;
    case -18754956:
         break;
    default:
         whatever();
    }
}

It works as intended, but there is this feeling that something can go awry.

What are the possible pitfalls of using that implementation? I am bound to use java 1.5 or 1.6 because corporate dictates so (therefore I cannot upgrade to 1.7 or later).

Is there some better implementation of a switch over Strings other than a monstruous chain of if-then-else (for the purpose of this question, lets assume I cannot do if-then-else over every possible String value of the input)?


related: What is the benefit of switching on Strings in Java 7? but I am asking pre-1.7

Best Answer

Hash codes are not unique. There are numerous strings which hash to, say, 1234546. If you want to check for the string "foo" and the unrelated, meaningless string "bar" has the same hash, your code will falsely treat "bar" the same as "foo" rather than rejecting it/going to default.

Fixing this is generally possible (check whether the value really equals the intended string in each case), but it's quite a bit of extra code, especially if there is a default case (since you have to transfer control out of the "wrong" case and to the default case). This is how the switch-over-string feature proposal desugars it. It's not pretty.

Hash codes are not meaningful. Someone has to find out the hash code and hard-code them, and the code has more meaningless magic numbers. You can and should of course write the string in a comment next to the integer literal, but it's still a maintenance burden.

Technically, the hash algorithm might also change when the JVM is updated or when the deployment environment is changed, etc. — depending on the JVM, maybe even when the JVM is restarted! And then the code would be silently wrong. This probably won't actually happen (I think the implementation of Java 7 switch-over-string depends on the compiler being able to predict the hashCode value of string literals).