StringBuilder vs StringBuffer: 10 Main Differences in Java

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

StringBuilder vs StringBuffer: which to choose and why does it matter?

\n\n

If you've ever written Java code that actively works with strings (for example, building an SQL query, forming JSON, or simply concatenating dozens of text pieces), you've likely faced the dilemma: StringBuilder or StringBuffer? On Stack Overflow, this question has gathered hundreds of thousands of views, and for good reason. At first glance, the classes look like twins — both extend AbstractStringBuilder, both use a mutable character array, both support append(), insert(), delete(). But as always, the devil is in the details.

\n\n

In this article, we won't just list the differences. We'll break them down with real examples, look under the hood of the JVM, and answer questions you'll definitely be asked in an interview. Let's go!

\n\n

1. The main difference: synchronization

\n\n

This is the most important point, the reason for the whole debate. StringBuffer is thread-safe. Almost all of its public methods are synchronized using the synchronized keyword. StringBuilder is not synchronized. That's it.

\n\n

Let's look at the code (simplified version from the real JDK):

\n\n
// StringBuffer (Java 17)\npublic synchronized StringBuffer append(String str) {\n    toStringCache = null;\n    super.append(str);\n    return this;\n}\n\n// StringBuilder\npublic StringBuilder append(String str) {\n    super.append(str);\n    return this;\n}\n
\n\n

One line of synchronized — and that's the entire difference. But this line changes everything: performance, use cases, even application architecture.

\n\n

When to use StringBuffer?

\n
    \n
  • You are writing a multithreaded application.
  • \n
  • The same instance of StringBuffer is used from multiple threads without external synchronization.
  • \n
  • Example: a logger that collects messages from different threads into a single buffer.
  • \n
\n\n

When to use StringBuilder?

\n
    \n
  • Single-threaded code (90% of cases).
  • \n
  • Local variables inside a method.
  • \n
  • Loops with string concatenation (the compiler itself will suggest StringBuilder).
  • \n
\n\n

2. Performance: which is faster?

\n\n

Here everything is predictable: StringBuilder is faster than StringBuffer. How much faster? It depends on the load, but on average 2-5 times. Let's test it with a simple benchmark.

\n\n
public class PerformanceTest {\n    private static final int ITERATIONS = 10_000_000;\n\n    public static void main(String[] args) {\n        // StringBuilder\n        long start = System.nanoTime();\n        StringBuilder sb = new StringBuilder();\n        for (int i = 0; i < ITERATIONS; i++) {\n            sb.append("a");\n        }\n        long sbTime = System.nanoTime() - start;\n\n        // StringBuffer\n        start = System.nanoTime();\n        StringBuffer sbf = new StringBuffer();\n        for (int i = 0; i < ITERATIONS; i++) {\n            sbf.append("a");\n        }\n        long sbfTime = System.nanoTime() - start;\n\n        System.out.println("StringBuilder: " + sbTime / 1_000_000 + " ms");\n        System.out.println("StringBuffer:  " + sbfTime / 1_000_000 + " ms");\n        System.out.println("Buffer is slower by " + (sbfTime / (double) sbTime) + " times");\n    }\n}\n
\n\n

On my laptop (Intel i7, 16GB RAM, Java 17) the result is consistent: StringBuilder ~180 ms, StringBuffer ~620 ms. The difference is almost 3.5 times. And if you add real work (parsing, formatting), the gap can increase. Why? Because every call to synchronized involves a monitor check, lock acquisition, and its release. In single-threaded code, this is pure overhead.

\n\n
\n Important: If your method guaran

Blogs

Book Recommendations