Why is using + to concatenate Strings in a loop slow, and what should you use instead?

Strings are immutable, so every += creates a new String and copies all the characters built so far. In a loop of n iterations that is O(n²) character copying, plus many temporary objects. A StringBuilder appends into one growing buffer, which is O(n) overall.

Key Points: • Outside loops, + is fine. Since Java 9 the compiler turns a single expression such as a + b + c into an efficient invokedynamic call (StringConcatFactory). • Inside a loop, each iteration still creates a new String, because the compiler can't merge separate statements. • StringBuilder is not synchronized and is the right choice in almost all code. StringBuffer is the synchronized, slower version. • Give StringBuilder an initial capacity when you know the approximate size, to avoid buffer resizing. • For joining collections, String.join() or Collectors.joining() are clearer than a manual loop.

Code Example:

public class ConcatPerformance {

    public static void main(String[] args) {
        int n = 20_000;

        long t1 = System.nanoTime();
        String s = "";
        for (int i = 0; i < n; i++) {
            s += i;                               // copies the whole string every time
        }
        long plusMs = (System.nanoTime() - t1) / 1_000_000;

        long t2 = System.nanoTime();
        StringBuilder sb = new StringBuilder(n * 5);
        for (int i = 0; i < n; i++) {
            sb.append(i);                         // appends into one buffer
        }
        String built = sb.toString();
        long sbMs = (System.nanoTime() - t2) / 1_000_000;

        System.out.println("Same result: " + s.equals(built));
        System.out.println("Length: " + built.length());
        System.out.println("StringBuilder at least 10x faster: " + (plusMs >= sbMs * 10));
    }
}

Output:

Same result: true Length: 88890 StringBuilder at least 10x faster: true

Good to Know: The example prints a comparison instead of raw milliseconds, because timings vary by machine. On a typical laptop the += loop takes hundreds of milliseconds, while StringBuilder takes about one millisecond. For precise numbers, use JMH.

Interview Tip: A concise interview answer is:

"Because Strings are immutable, each += in a loop creates a new String and copies everything built so far, which is O(n²). StringBuilder appends into one resizable buffer, so it's O(n). A single expression like a + b + c is fine, since the compiler optimises it, but inside loops I use StringBuilder, or String.join and Collectors.joining for collections."

Previous question: What does String.intern() do, and when should you use it?

Next question: What is the difference between String.valueOf(), toString() and concatenating with "" when converting to a String?

More Java Strings interview questions

All Java Strings questions