Question

StringBuilder vs StringBuffer in Java: Differences and Performance

javastringbuilderstringbuffer

Question

In Java, what is the main difference between StringBuffer and StringBuilder?

Are there any performance considerations when choosing one over the other?

Short Answer

By the end of this page, you will understand how StringBuilder and StringBuffer work in Java, why both exist, what thread safety means in this context, and how their performance differs. You will also learn when to use each one in real programs.

Concept

StringBuilder and StringBuffer are both mutable sequence classes in Java. They are used when you need to build or modify strings efficiently.

Java String objects are immutable, which means once a string is created, it cannot be changed. If you repeatedly combine strings with +, Java often creates many temporary objects. That can be inefficient in loops or repeated text-building tasks.

That is where StringBuilder and StringBuffer help.

Core difference

The main difference is thread safety:

  • StringBuffer is synchronized, so it is thread-safe.
  • StringBuilder is not synchronized, so it is not thread-safe.

Because StringBuffer adds synchronization, it usually has more overhead. In single-threaded code, StringBuilder is typically faster.

Why this matters

In real programming, choosing between them depends on whether multiple threads may modify the same object at the same time.

  • If only one thread uses the object, StringBuilder is usually the right choice.
  • If multiple threads share and modify the same mutable character sequence, StringBuffer provides built-in synchronization.

In practice, StringBuilder is more commonly used because many string-building tasks happen inside a method or request where the object is not shared across threads.

Important note

Thread safety is not automatically needed just because your application is multithreaded. The question is whether the same instance is shared and modified by multiple threads. If not, StringBuilder is still fine.

Mental Model

Think of both classes as editable notepads:

  • StringBuilder is a regular notepad on your desk. It is quick and easy to write on, but if several people try to write on it at the same time, the result may become messy.
  • StringBuffer is the same notepad, but with a rule: only one person can write at a time. That makes it safer for shared use, but slower because people must wait their turn.

So the trade-off is simple:

  • Speed: StringBuilder
  • Safety for shared access: StringBuffer
Take Quiz

Syntax and Examples

Both classes have very similar APIs.

Basic syntax

StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" ");
sb.append("World");
String result = sb.toString();
StringBuffer sbf = new StringBuffer();
sbf.append("Hello");
sbf.append(" ");
sbf.append("World");
String result = sbf.toString();

Example with StringBuilder

public class Main {
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder();

        builder.append("Java");
        builder.append(" is ");
        builder.append("fast");

        System.out.println(builder.toString());
    }
}

Output:

Java is fast

This is efficient because the same mutable object is updated instead of creating a new String each time.

Example with StringBuffer

public class Main {
    public static void main(String[] args) {
        StringBuffer buffer = new StringBuffer();

        buffer.append("Safe");
        buffer.append(" text");

        System.out.println(buffer.toString());
    }
}

Output:

Safe text

The usage looks almost identical. The main difference is not syntax, but synchronization behavior.

Step by Step Execution

Consider this example:

StringBuilder builder = new StringBuilder();
builder.append("A");
builder.append("B");
builder.append("C");
String result = builder.toString();

Step by step:

  1. new StringBuilder() creates an empty mutable character container.
  2. append("A") adds A to the container.
    • Current content: A
  3. append("B") adds B to the end.
    • Current content: AB
  4. append("C") adds C to the end.
    • Current content: ABC
  5. toString() creates a regular immutable String containing ABC.
  6. result now refers to the final string: "ABC".

Now compare that idea to repeated string concatenation:

String text = "";
text = text + "A";
text = text + "B";
text = text + "C";

Conceptually, this creates new String objects as the value changes, because String is immutable. That is why builders are often preferred for repeated updates.

Real World Use Cases

Here are common situations where StringBuilder or StringBuffer is useful:

Building API responses or messages

StringBuilder message = new StringBuilder();
message.append("User: ").append(username).append(" logged in at ").append(time);

Generating CSV or text files

StringBuilder csv = new StringBuilder();
csv.append("id,name\n");
csv.append("1,Alice\n");
csv.append("2,Bob\n");

Building SQL or dynamic queries carefully

StringBuilder query = new StringBuilder("SELECT * FROM users WHERE 1=1");
if (activeOnly) {
    query.append(" AND active = true");
}

Creating logs efficiently inside loops

StringBuilder log = new StringBuilder();
for (int i = 0; i < 3; i++) {
    log.append("Step ").append(i).append(" completed\n");
}

Shared legacy code with synchronization needs

Older or shared code may still use StringBuffer when multiple threads are expected to modify the same buffer.

Take Quiz

Real Codebase Usage

In real Java codebases, developers usually follow these patterns:

Use StringBuilder for local string construction

Inside a method, if the object is created and used only there, StringBuilder is the usual choice.

public String formatName(String firstName, String lastName) {
    StringBuilder builder = new StringBuilder();
    builder.append(lastName).append(", ").append(firstName);
    return builder.toString();
}

Use chaining for readability

String result = new StringBuilder()
        .append("Total: ")
        .append(42)
        .append(" items")
        .toString();

Pre-size when large output is expected

If you know the text will be large, you can reduce resizing overhead.

StringBuilder builder = new StringBuilder(1000);

Avoid sharing mutable builders across threads

A common pattern is to keep builders local rather than shared. This avoids synchronization issues and keeps code simpler.

Prefer other synchronization strategies when appropriate

Even in multithreaded applications, developers often avoid sharing a mutable buffer at all. Instead of choosing StringBuffer, they may redesign the code so each thread uses its own StringBuilder. That is often simpler and faster.

Validation and formatting

Builders are often used after guard clauses and validation logic.

public String createLabel(String name, int id) {
    if (name == null || name.isBlank()) {
        return "Invalid name";
    }

    return new StringBuilder()
            .append("User[")
            .append(id)
            .append("]: ")
            .append(name)
            .toString();
}

Common Mistakes

1. Thinking StringBuffer is always better because it is thread-safe

Thread safety is useful only when the same object is actually shared between threads.

If the buffer is local to one method, StringBuilder is usually the better default.

2. Using StringBuilder in shared mutable multithreaded code

Broken example:

public class SharedText {
    private static StringBuilder builder = new StringBuilder();

    public static void addText(String text) {
        builder.append(text);
    }
}

If multiple threads call addText, the result may be corrupted or unpredictable.

3. Assuming + is always bad

For small, simple concatenations, + is often perfectly fine and more readable.

String fullName = firstName + " " + lastName;

You usually switch to StringBuilder when concatenation is repeated, especially inside loops.

4. Forgetting to call toString()

StringBuilder is not the same type as String.

Broken example:

StringBuilder builder = new StringBuilder();
builder.append("Hello");
// String text = builder; // compile error

Correct:

String text = builder.toString();

5. Sharing a mutable builder by accident

Even if your app uses multiple threads, local variables are usually safe because each method call gets its own variable.

Safer example:

public String buildMessage(String name) {
    StringBuilder builder = new StringBuilder();
    builder.append("Hello ").append(name);
    return builder.toString();
}

6. Ignoring capacity for very large builds

If you append a lot of content, the internal array may resize multiple times. You can reduce that by setting an initial capacity.

StringBuilder builder = new StringBuilder(5000);

Comparisons

FeatureStringStringBuilderStringBuffer
MutableNoYesYes
Thread-safeYes, because immutableNoYes
Synchronized methodsNoNoYes
Usually faster for repeated modificationNoYesUsually slower than StringBuilder
Best use caseFixed text valuesSingle-threaded string buildingShared mutable string building

StringBuilder vs StringBuffer

AspectStringBuilderStringBuffer
SynchronizationNoYes
PerformanceFaster in most single-threaded casesSlower due to synchronization overhead
Thread safetyNot safe for shared concurrent modificationSafe for shared concurrent modification
Common modern defaultYesLess common

+ vs builder classes

SituationBest choice
One or two simple concatenations+
Repeated concatenation in a loopStringBuilder
Shared mutable text across threadsStringBuffer or redesign to avoid sharing
Take Quiz

Cheat Sheet

Quick rule

  • Use StringBuilder by default for repeated string modification.
  • Use StringBuffer only when the same mutable buffer must be shared safely across threads.

Core difference

StringBuilder builder = new StringBuilder();   // not synchronized
StringBuffer buffer = new StringBuffer();      // synchronized

Common methods

append()
insert()
delete()
reverse()
length()
capacity()
toString()

Example

StringBuilder sb = new StringBuilder();
sb.append("Hello").append(" ").append("Java");
String result = sb.toString();

Performance rule

  • StringBuilder is usually faster.
  • StringBuffer has synchronization overhead.
  • For small simple expressions, + is often fine.

Best practices

  • Keep builders local to methods.
  • Use toString() to get a String.
  • Set initial capacity for large outputs.
StringBuilder sb = new StringBuilder(1000);

Edge case to remember

A multithreaded application does not automatically require StringBuffer. It is only needed if the same instance is shared and modified by multiple threads.

FAQ

What is the main difference between StringBuilder and StringBuffer in Java?

StringBuffer is synchronized and thread-safe. StringBuilder is not synchronized and is usually faster.

Is StringBuilder faster than StringBuffer?

Yes, in most single-threaded cases StringBuilder is faster because it does not pay synchronization cost.

When should I use StringBuffer?

Use it when multiple threads must safely modify the same mutable character sequence.

Should I always use StringBuilder instead of String?

No. For simple one-off concatenations, regular String with + is often clearer and perfectly acceptable.

Is StringBuilder thread-safe if each thread creates its own instance?

Yes. If each thread uses its own separate instance, there is no shared mutable state problem.

Why are strings immutable in Java?

Immutability improves safety, predictability, and makes strings easier to share and optimize.

Do StringBuilder and StringBuffer have the same methods?

They have very similar APIs, including methods like append(), insert(), delete(), and toString().

Take Quiz

Mini Project

Description

Build a small Java utility that generates a formatted order summary. This project demonstrates why StringBuilder is useful when combining many pieces of text into one final output.

Goal

Create a method that builds a multi-line receipt string efficiently using StringBuilder.

Requirements

[ "Create a method that accepts a customer name and a list of item names.", "Build a multi-line receipt using StringBuilder.", "Include a header, each item on its own line, and a total item count.", "Return the final result as a String." ]

Take Quiz

Keep learning

Related questions

View more