What is the difference between String, StringBuilder and StringBuffer?
String is immutable, so every change creates a new object. StringBuilder and StringBuffer are mutable and change the same object in place. StringBuffer's methods are synchronized (thread-safe but slower), while StringBuilder is not synchronized and is the usual choice for building strings in a single thread.
Explain it simply
A String is like a printed certificate. If you want to change the name on it, you cannot edit the paper; you print a fresh certificate. A StringBuilder is like a whiteboard: you can write, erase and add text on the same board as many times as you like.
A StringBuffer is the same whiteboard, but with a rule that only one person may hold the marker at a time. That rule keeps things safe when many people (threads) share the board, but it slows everyone down a little, even when only one person is writing.
Example
public class Builders {
public static void main(String[] args) {
String s = "AI";
s.concat(" Tapri"); // result is thrown away
System.out.println(s); // prints: AI
s = s.concat(" Tapri"); // new String object assigned back
System.out.println(s); // prints: AI Tapri
StringBuilder sb = new StringBuilder("Order");
sb.append(" #").append(1042).append(" placed");
System.out.println(sb); // prints: Order #1042 placed
sb.reverse();
System.out.println(sb); // prints: decalp 2401# redrO
}
}How it works
| String | StringBuilder | StringBuffer | |
|---|---|---|---|
| Mutable | No | Yes | Yes |
| Thread-safe | Yes (because immutable) | No | Yes (synchronized methods) |
| Speed for many changes | Slow | Fastest | Slower than StringBuilder |
| Added in | Java 1.0 | Java 5 | Java 1.0 |
Inside, StringBuilder and StringBuffer keep a resizable character array. append writes into that array and grows it only when it runs out of space. A String cannot be changed, so s = s + x in a loop creates a new string and copies all the old characters each time. For a loop of n steps that adds up to roughly O(n²) work.
Real-world use
- Building a long CSV row, an SQL query string, or a message like a Swiggy order summary inside a loop: use
StringBuilder. - Keys in a
HashMap, constants, user names, anything that should not change: useString. Immutability makes strings safe to share and lets their hash code be cached. StringBuffermostly appears in old code. If several threads really need to build one string together, there are usually better designs.
Common mistakes
- Using
+inside a large loop. One+in a single expression is fine; the compiler optimises it. The cost comes from repeating it in a loop. - Thinking
s.toUpperCase()changess. It returns a new string; you must assign it. - Choosing
StringBuffer"to be safe" in single-threaded code. It only adds locking cost. - Comparing two
StringBuilderobjects withequals(). It is not overridden, so it compares references. Convert withtoString()first, or usecompareTo(Java 11+).
What to say in the interview
"String is immutable, so any change gives a new object, which makes it safe to share and good as a map key, but slow for repeated changes. StringBuilder and StringBuffer are both mutable and append into an internal buffer. The difference is that StringBuffer's methods are synchronized, so it is thread-safe but slower, while StringBuilder is not synchronized. In practice I use String for fixed values and StringBuilder when I build a string in a loop."
Follow-up questions
- Why is String immutable in Java?
- What is the default capacity of a StringBuilder, and how does it grow?
- Is
"a" + "b" + "c"slow? - How would you reverse a string in Java?
Go deeper
Read these once the basics above feel easy.
A new StringBuilder() starts with a capacity of 16 characters. When it fills up it allocates a larger array (roughly double the old size plus two) and copies the content. If you know the final size, pass it to the constructor, for example new StringBuilder(1000), to avoid repeated copying. For a single concatenation expression, modern Java (9 and later) compiles + to an invokedynamic call that builds the result efficiently, so "Hi " + name + "!" does not need a manual builder. The advice to use StringBuilder is specifically about loops.