String vs StringBuilder vs StringBuffer
TL;DR
| Feature | String | StringBuilder | StringBuffer |
|---|---|---|---|
| Mutability | Immutable | Mutable | Mutable |
| Thread Safety | Safe | Not Safe | Safe (Synchronized) |
| Performance | Slow (if concatenated) | Fast | Slow (due to locks) |
Concept
Because String objects are immutable, repeatedly concatenating them (e.g., inside a loop) is extremely inefficient. Every concatenation creates a brand new String object, consuming memory and CPU.
To solve this, Java provides Mutable string classes:
StringBuilder: A mutable sequence of characters. It is the preferred class for modifying strings because it is very fast.StringBuffer: Exactly likeStringBuilder, but all of its methods aresynchronized. This makes it thread-safe (multiple threads can use it safely), but significantly slower.
Examples
public class StringPerformance {
public static void main(String[] args) {
// 1. Inefficient (Creates 1000 new String objects!)
String str = "";
for (int i = 0; i < 1000; i++) {
str += i;
}
// 2. Efficient (Modifies the existing internal array)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
String result = sb.toString();
// 3. Thread-Safe (Use only when accessed by multiple threads concurrently)
StringBuffer buffer = new StringBuffer();
buffer.append("Safe");
}
}
Interview Questions
Q: When should you use StringBuilder over String?
A: You should use StringBuilder whenever you are constructing a string dynamically inside a loop, or combining many separate strings, to avoid the overhead of creating numerous temporary immutable String objects.
Q: Since Java 8/9, does the compiler automatically optimize String concatenation?
A: Yes. If you write String s = "a" + "b" + "c";, the compiler optimizes this automatically (historically using StringBuilder under the hood, and since Java 9 using StringConcatFactory via invokedynamic). However, the compiler cannot optimize concatenations that occur across multiple iterations of a for or while loop. You must explicitly use StringBuilder for loops.