During an interview, I was posed an intriguing question about how the Java Virtual Machine (JVM) handles a switch
statement involving a String
type. Specifically, I was asked whether the JVM employs LookupSwitch
or TableSwitch
for this operation. My initial thought was that it would utilize LookupSwitch
due to the sparsity of String
hashcodes. However, the interviewer added a layer of complexity by asking: "How does the JVM handle hash collisions when two different cases have the same hashcode?"
class Solution {
static int switchString(String i) {
int res;
switch (i) {
case "A": // hashcode 65
res = 0;
break;
case "FB": // hashcode 2236
res = 1;
break;
case "Ea": // hashcode 2236
res = 2;
break;
default:
res = 3;
}
return res;
}
public static void main(String[] args) {
System.out.println(switchString("Ea"));
}
}
Can you help clarify how the JVM navigates through switch cases involving String
objects, especially when hash collisions are involved?
For the first part question, I found I'm wrong here. the compiler has to pick either, a lookupswitch or tableswitch instruction
I've seen the decompiled .class bytecode
class Solution {
Solution() {
}
static int switchString(String i) {
byte var3 = -1;
switch(i.hashCode()) {
case 65:
if (i.equals("A")) {
var3 = 0;
}
break;
case 2236:
if (i.equals("Ea")) {
var3 = 2;
} else if (i.equals("FB")) {
var3 = 1;
}
}
byte res;
switch(var3) {
case 0:
res = 0;
break;
case 1:
res = 1;
break;
case 2:
res = 2;
break;
default:
res = 3;
}
return res;
}
public static void main(String[] args) {
System.out.println(switchString("Ea"));
}
}
After examining the decompiled .class
bytecode, it's apparent that the approach depends on the sparsity of the hashcodes of the strings, opting for either lookupswitch
or tableswitch
. In cases of hash collisions, the JVM employs a sequence of equals
operations to distinguish between the colliding strings. This process involves a double switch
mechanism to manage different cases effectively.