Java Switch Performance: Should You Use String or int?
Using JMH, this article benchmarks Java switch statements, comparing the traditional int‑based switch (via String hashCode) against the newer String‑based switch, showing that the int version runs roughly twice as fast while warning about hashCode collisions.
Scenario
Java developers can use JMH (Java Microbenchmark Harness) to measure and improve the performance of switch‑case statements, specifically comparing the cost of switching on a String versus an int derived from the string’s hashCode().
Optimization Idea
Before JDK 1.7, switch only accepted int values. Starting with JDK 1.7, the compiler translates a String switch into a series of hashCode() comparisons, effectively turning the switch into an int switch internally. By explicitly converting the String to its int hash code, the per‑case if checks are eliminated, potentially improving performance.
Precautions
Hash code collisions must be considered. For example, the strings "Aa" and "BB" both produce the hash code 2112. When using hash codes as switch keys, the set of strings should be verified to have unique hash values to avoid incorrect case selection.
Performance Test Setup
First, the hash codes of candidate strings are printed to ensure uniqueness:
System.out.println("1".hashCode()); // 49
System.out.println("3".hashCode()); // 51
System.out.println("5".hashCode()); // 53
System.out.println("7".hashCode()); // 55
System.out.println("9".hashCode()); // 57
System.out.println("Aa".hashCode()); // 2112
System.out.println("BB".hashCode()); // 2112Only the non‑colliding strings "1", "3", "5", "7", and "9" are used in the benchmark.
The JMH benchmark class is defined as follows:
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@State(Scope.Thread)
public class SwitchOptimizeTest {
static String _NUM = "9";
public static void main(String[] args) throws RunnerException {
Options options = new OptionsBuilder()
.include(SwitchOptimizeTest.class.getSimpleName())
.build();
new Runner(options).run();
}
@Benchmark
public void switchString() {
int num1;
switch (_NUM) {
case "1": num1 = 1; break;
case "3": num1 = 3; break;
case "5": num1 = 5; break;
case "7": num1 = 7; break;
case "9": num1 = 9; break;
default: num1 = -1; break;
}
}
@Benchmark
public void switchInt() {
int num1;
switch (_NUM.hashCode()) {
case 49: num1 = 1; break;
case 51: num1 = 3; break;
case 53: num1 = 5; break;
case 55: num1 = 7; break;
case 57: num1 = 9; break;
default: num1 = -1; break;
}
}
}Benchmark Results
The JMH output shows the average execution time for each method:
// Benchmark Mode Cnt Score Error Units
// SwitchOptimizeTest.switchInt avgt 5 1.214 ± 0.101 ns/op
// SwitchOptimizeTest.switchString avgt 5 2.924 ± 0.226 ns/opThus, switching on the pre‑computed int hash code is roughly twice as fast as switching directly on the String. The accompanying chart (image) visualizes this difference.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
The Dominant Programmer
Resources and tutorials for programmers' advanced learning journey. Advanced tracks in Java, Python, and C#. Blog: https://blog.csdn.net/badao_liumang_qizhi
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
