In Java, all three—String, StringBuffer, and StringBuilder—are used to handle text, but they have key differences in terms of mutability, performance, and thread safety.
1. Summary of Differences
| Feature | String | StringBuffer | StringBuilder |
|---|---|---|---|
| Mutability | ❌ Immutable (cannot be changed) | ✅ Mutable (can be changed) | ✅ Mutable (can be changed) |
| Thread Safety | ✅ Yes (Immutable, thread-safe by design) | ✅ Yes (Synchronized methods) | ❌ No (Not synchronized) |
| Performance | ❌ Slow (new object created for every modification) | ⚠️ Moderate (thread-safe, but slower due to synchronization) | ✅ Fastest (no synchronization overhead) |
| Usage | For fixed text (e.g., keys, constants, config values) | For multi-threaded modifications | For single-threaded modifications |
| Example | "Hello" | new StringBuffer("Hello") | new StringBuilder("Hello") |
2. String (Immutable)
A String object cannot be changed once created. Any modification creates a new object.
Example: Why String is Immutable
public class StringExample {
public static void main(String[] args) {
String s = "Hello";
s.concat(" World"); // Creates a new object but doesn't change `s`
System.out.println(s); // Output: Hello
}
}
🔹 Why? "Hello" stays unchanged because String is immutable.
✅ Use String when:
- You have constant values.
- You don’t need frequent modifications.
3. StringBuffer (Mutable & Thread-Safe)
StringBufferis mutable, meaning you can change its content without creating new objects.- It is synchronized, making it thread-safe but slower than
StringBuilder.
Example: Using StringBuffer
public class StringBufferExample {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("Hello");
sb.append(" World");
System.out.println(sb); // Output: Hello World
}
}
✅ Use StringBuffer when:
- You need thread-safe string modifications (used in multi-threading).
- You are concatenating or modifying strings frequently.
🚨 Downside: Slower than StringBuilder because it is synchronized.
4. StringBuilder (Mutable & Fastest)
StringBuilderis just likeStringBufferbut not synchronized.- It is faster than
StringBufferin single-threaded applications.
Example: Using StringBuilder
public class StringBuilderExample {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
System.out.println(sb); // Output: Hello World
}
}
✅ Use StringBuilder when:
- You are working in a single-threaded environment.
- You need high-performance string modification.
🚀 Benefit: Fastest option because it avoids synchronization.
5. Performance Comparison (String vs. StringBuffer vs. StringBuilder)
Let’s compare their speeds in string concatenation.
public class PerformanceTest {
public static void main(String[] args) {
int iterations = 100000;
long start, end;
// Test String (Slowest)
start = System.nanoTime();
String str = "";
for (int i = 0; i < iterations; i++) {
str += "a"; // New object created each time
}
end = System.nanoTime();
System.out.println("String time: " + (end - start) / 1_000_000.0 + " ms");
// Test StringBuffer (Thread-Safe)
start = System.nanoTime();
StringBuffer sbf = new StringBuffer();
for (int i = 0; i < iterations; i++) {
sbf.append("a");
}
end = System.nanoTime();
System.out.println("StringBuffer time: " + (end - start) / 1_000_000.0 + " ms");
// Test StringBuilder (Fastest)
start = System.nanoTime();
StringBuilder sbd = new StringBuilder();
for (int i = 0; i < iterations; i++) {
sbd.append("a");
}
end = System.nanoTime();
System.out.println("StringBuilder time: " + (end - start) / 1_000_000.0 + " ms");
}
}
Expected Output (Typical Results)
String time: 1200 ms
StringBuffer time: 8 ms
StringBuilder time: 5 ms
✅ Why is String so slow?
- Every modification creates a new object, consuming more memory and processing time.
✅ Why is StringBuilder fastest?
- It modifies the same object without synchronization overhead.
6. When to Use Which One?
| Scenario | Best Choice | Why? |
|---|---|---|
| Fixed text (constants, keys, messages) | String | Immutable & safe |
| String concatenation in a loop (single-threaded) | StringBuilder | Fastest (no synchronization) |
| Multi-threaded string modifications | StringBuffer | Thread-safe (synchronized) |
| Reading and modifying a large string (single-threaded) | StringBuilder | Best for performance |
| Web applications storing constant values | String | Optimized with the String Pool |
Conclusion
- ✅ Use
Stringwhen immutability is required (e.g., constants, database keys). - ✅ Use
StringBuilderwhen working in a single-threaded application (fastest option). - ✅ Use
StringBufferwhen multiple threads modify the string (thread-safe but slower).