Difference Between StringBuffer and StringBuilder in Java
StringBuffer and StringBuilder are both mutable sequences of characters with the same methods (append, insert, delete, reverse…), the same internal growable array and the same capacity rules. The only real difference is synchronization:
StringBuffer(Java 1.0): every public method issynchronized, so one instance can be shared between threads.StringBuilder(Java 5): no synchronization, so it is faster, and it is the right choice whenever the object is used by a single thread, which is nearly always.
1. Comparison Table
| Aspect | StringBuffer | StringBuilder |
|---|---|---|
| Synchronization | All public methods synchronized | None |
| Thread safety | Safe for individual calls | Not thread-safe |
| Performance | Slower (locking overhead) | Faster |
| Introduced | Java 1.0 | Java 5 |
| API | Identical: both extend AbstractStringBuilder and implement CharSequence, Appendable, Comparable (11) | |
| Capacity | Default 16; grows to (old × 2) + 2 | |
equals() | Not overridden in either: compares references | |
| Recommended for | A buffer shared by threads, legacy APIs | Everything else |
2. Identical API
public class SameApi {
public static void main(String[] args) {
StringBuffer buffer = new StringBuffer("Java");
StringBuilder builder = new StringBuilder("Java");
// Identical API and results
buffer.append(" 21").insert(0, "Hello ").reverse().reverse();
builder.append(" 21").insert(0, "Hello ").reverse().reverse();
System.out.println("StringBuffer : " + buffer + " (capacity " + buffer.capacity() + ")");
System.out.println("StringBuilder : " + builder + " (capacity " + builder.capacity() + ")");
System.out.println("same text : " + buffer.toString().equals(builder.toString()));
System.out.println("common type : " + (buffer instanceof CharSequence) + ", " + (builder instanceof CharSequence));
}
}
StringBuffer : Hello Java 21 (capacity 20) StringBuilder : Hello Java 21 (capacity 20) same text : true common type : true, true
Because the APIs are identical, switching from StringBuffer to StringBuilder is usually just a change of type name.
3. Thread Safety
Two threads append 20,000 characters each to one shared object:
public class SharedBetweenThreads {
static int run(Appendable target) throws InterruptedException {
Runnable task = () -> {
for (int i = 0; i < 20_000; i++) {
try { target.append('x'); } catch (Exception e) { /* corrupted internal state */ }
}
};
Thread a = new Thread(task), b = new Thread(task);
a.start(); b.start(); a.join(); b.join();
return ((CharSequence) target).length();
}
public static void main(String[] args) throws InterruptedException {
System.out.println("expected : 40000");
System.out.println("StringBuffer : " + run(new StringBuffer()));
System.out.println("StringBuilder : " + run(new StringBuilder()) + " (often less when shared)");
}
}
expected : 40000 StringBuffer : 40000 StringBuilder : 20478 (often less when shared)
A shared StringBuilder loses characters or even throws exceptions. In real programs, though, you rarely share a string builder between threads: each thread usually builds its own text and then publishes the finished String, which needs no synchronization.
4. Performance
public class SpeedCompare {
public static void main(String[] args) {
int n = 5_000_000;
for (int warm = 0; warm < 3; warm++) { // let the JIT warm up
new StringBuffer().append("x".repeat(10));
new StringBuilder().append("x".repeat(10));
}
long t0 = System.nanoTime();
StringBuffer sbf = new StringBuffer();
for (int i = 0; i < n; i++) sbf.append('x');
long t1 = System.nanoTime();
StringBuilder sbd = new StringBuilder();
for (int i = 0; i < n; i++) sbd.append('x');
long t2 = System.nanoTime();
System.out.printf("StringBuffer : %3d ms%n", (t1 - t0) / 1_000_000);
System.out.printf("StringBuilder : %3d ms%n", (t2 - t1) / 1_000_000);
}
}
StringBuffer : 16 ms StringBuilder : 7 ms
The JIT can sometimes remove uncontended locks, so the gap varies, but StringBuilder is never slower in single-threaded code.
5. Which Should You Use?
StringBuilderby default: local variables, methods, loops,toString()implementations.StringBufferonly if a single instance is truly appended to by several threads, or an older API requires it.Stringfor the finished, immutable result. See String vs StringBuffer.
6. Summary
- Both are mutable character sequences with the same API and capacity behaviour.
StringBufferis synchronized and thread-safe per call;StringBuilderis not.StringBuilderis faster and is the standard choice.- Neither overrides
equals; compare contents explicitly.
Related Tutorials
Frequently Asked Questions (FAQ)
Q1. What is the difference between StringBuffer and StringBuilder?
StringBuffer is synchronized and thread-safe; StringBuilder is not synchronized and therefore faster. Otherwise they are the same.
Q2. Which is faster?
StringBuilder, because it does not acquire locks.
Q3. Which should I use by default?
StringBuilder.
Q4. When was StringBuilder introduced?
In Java 5, as an unsynchronized replacement for StringBuffer.
Q5. Do they have the same methods?
Yes. Both extend AbstractStringBuilder and offer the same API.
Q6. Is StringBuilder ever thread-safe?
Only if it is confined to one thread, for example as a local variable. Sharing it needs external synchronization.
Q7. Is a StringBuffer fully safe for multi-step operations?
No. Each call is atomic, but a sequence like "check length, then append" can interleave with other threads.
Q8. What is the default capacity of both?
16 characters, or 16 plus the initial string's length.
Q9. Do they override equals()?
No. Both compare by reference; use compareTo (Java 11) or toString().equals().
Q10. Can I convert between them?
Yes: new StringBuilder(buffer) or new StringBuffer(builder), since both accept a CharSequence.
Q11. Are both final classes?
Yes.
Q12. Is StringBuffer deprecated?
No, but it is rarely needed in modern code.
Q13. Which does the + operator use?
Before Java 9 the compiler generated StringBuilder calls; since Java 9 it uses invokedynamic string concatenation.
Q14. Which is better in a web application?
StringBuilder. Each request handles its own local builder, so no synchronization is required.
Q15. Do both implement Comparable?
Yes, since Java 11, comparing their contents lexicographically.
Q16. Can I reverse a string with either?
Yes: new StringBuilder(s).reverse().toString() works identically with StringBuffer.
Q17. What happens if two threads share a StringBuilder?
Characters may be lost, data corrupted, or ArrayIndexOutOfBoundsException thrown during resizing.
Q18. Is there a performance difference with one thread?
Yes, usually small but measurable; StringBuilder avoids lock acquisition entirely.
Q19. Which is better for virtual threads?
StringBuilder, used locally in each task, just as with platform threads.
Q20. Is this asked in interviews?
Very often, usually together with String. Mention mutability, synchronization, performance and the Java 5 introduction of StringBuilder.