Fundamentals 7 min read

Why ‘+’ Can Outperform StringBuilder in Java: Real Benchmarks Explained

This article investigates the performance differences between Java’s ‘+’ operator, StringBuilder, and StringJoiner for string concatenation, presenting JUnit benchmark results for single and looped concatenations, analyzing compiled bytecode, and concluding when each method is optimal for readability and speed.

macrozheng
macrozheng
macrozheng
Why ‘+’ Can Outperform StringBuilder in Java: Real Benchmarks Explained

When concatenating strings in Java, developers often see IDE warnings suggesting the use of StringBuffer, StringBuilder, or StringJoiner, but the IDE may also recommend using the '+' operator.

Report any usage of StringBuffer, StringBuilder, or StringJoiner that could be replaced by a single java.lang.String concatenation. Using string concatenation makes the code shorter and simpler. The check reports only when the resulting concatenation is at least as efficient as the original code.

Normal Concatenation

Simple concatenation using '+' is commonly believed to be less efficient than StringBuilder, but since JDK 5 the compiler automatically transforms '+' operations into StringBuilder calls.

<code>/**
 * Use + to concatenate strings
 */
public String concatenationStringByPlus(String prefix, int i) {
    return prefix + "-" + i;
}

/**
 * Use StringBuilder to concatenate strings
 */
public String concatenationStringByStringBuilder(String prefix, int i) {
    return new StringBuilder().append(prefix).append("-").append(i).toString();
}

/**
 * Test + concatenation performance
 */
@Test
public void testStringConcatenation01ByPlus() {
    long startTime = System.currentTimeMillis();
    int count = 100000;
    for (int i = 0; i < count; i++) {
        String str = concatenationStringByPlus("testStringConcatenation01ByStringBuilder:", i);
    }
    long endTime = System.currentTimeMillis();
    System.out.println("testStringConcatenation01ByPlus, concatenated " + count + " times, took " + (endTime - startTime) + " ms");
}

/**
 * Test StringBuilder concatenation performance
 */
@Test
public void testStringConcatenation02ByStringBuilder() {
    long startTime = System.currentTimeMillis();
    int count = 100000;
    for (int i = 0; i < count; i++) {
        String str = concatenationStringByStringBuilder("testStringConcatenation02ByStringBuilder:", i);
    }
    long endTime = System.currentTimeMillis();
    System.out.println("testStringConcatenation02ByStringBuilder, concatenated " + count + " times, took " + (endTime - startTime) + " ms");
}
</code>

Running the JUnit tests yields:

<code>testStringConcatenation01ByPlus, concatenated 100000 times, took 33 ms
testStringConcatenation02ByStringBuilder, concatenated 100000 times, took 36 ms
</code>

The difference is minimal; considering the large number of iterations, the per‑operation cost is negligible, and various runtime factors can affect timing, so the two approaches are effectively equivalent for single concatenations.

Decompiling the compiled class file with

javap -c StringTest.class

shows that both methods generate identical bytecode, confirming equal performance.

Since the performance is the same, using '+' for simple concatenation is recommended for its brevity and readability.

Loop Concatenation

When concatenating inside a loop, using '+' creates a new

StringBuilder

on each iteration, dramatically increasing overhead. Directly reusing a single

StringBuilder

instance is far more efficient.

<code>/**
 * Loop concatenation using +
 */
@Test
public void testLoopStringConcatenation03ByPlus() {
    long startTime = System.currentTimeMillis();
    int count = 10000;
    String str = "testLoopStringConcatenation03ByPlus:";
    for (int i = 0; i < count; i++) {
        str = str + "-" + i;
    }
    System.out.println(str);
    long endTime = System.currentTimeMillis();
    System.out.println("testLoopStringConcatenation03ByPlus, concatenated " + count + " times, took " + (endTime - startTime) + " ms");
}

/**
 * Loop concatenation using StringBuilder
 */
@Test
public void testLoopStringConcatenation04ByStringBuilder() {
    long startTime = System.currentTimeMillis();
    int count = 10000;
    StringBuilder stringBuilder = new StringBuilder("testLoopStringConcatenation04ByStringBuilder:");
    for (int i = 0; i < count; i++) {
        stringBuilder.append("-");
        stringBuilder.append(i);
    }
    String str = stringBuilder.toString();
    System.out.println(str);
    long endTime = System.currentTimeMillis();
    System.out.println("testLoopStringConcatenation04ByStringBuilder, concatenated " + count + " times, took " + (endTime - startTime) + " ms");
}
</code>

Test results:

<code>testLoopStringConcatenation03ByPlus, concatenated 10000 times, took 463 ms
testLoopStringConcatenation04ByStringBuilder, concatenated 10000 times, took 13 ms
</code>

The loop using '+' is orders of magnitude slower than the StringBuilder version.

Conclusion

For simple, non‑looped string concatenation, using '+' is faster and more concise.

For concatenation inside loops, '+' incurs significant overhead; prefer StringBuilder for better performance.

JavaperformanceJunitStringBuilderString Concatenation
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.