Table of Contents
Why String Operations Can Be Slow
Java Strings are immutable – every modification creates a new object. This leads to hidden inefficiencies in loops or heavy text processing. Let’s fix these bottlenecks.
1. The Problem with +
in Loops
Using +
for concatenation in loops generates temporary String objects, wasting memory and CPU cycles.
❌ Inefficient Example:
String result = "";
for (int i = 0; i < 1000; i++) {
result += i; // Creates 1000+ objects!
}
Time Complexity: O(n²) – Each iteration copies the entire result
string.
2. Solution: Use StringBuilder
StringBuilder
is a mutable sequence of characters designed for high-performance modifications.
✅ Optimized Example:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i); // Modifies internal buffer directly
}
String result = sb.toString();
Time Complexity: O(n) – Appends in constant time (amortized).
3. StringBuilder
vs StringBuffer
Feature | StringBuilder | StringBuffer |
---|---|---|
Thread Safety | Not thread-safe (faster) | Thread-safe (synchronized) |
Performance | Faster in single-threaded | Slower due to locks |
When to Use | Most cases (default choice) | Legacy code or multithreaded contexts |
Example:
// Single-threaded → Use StringBuilder
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
// Multi-threaded → Use StringBuffer (rarely needed)
StringBuffer buffer = new StringBuffer("Hello");
buffer.append(" World");
4. Pre-Sizing StringBuilder
Initialize StringBuilder
with an estimated capacity to minimize internal array resizing:
// Default capacity: 16 chars → Frequent resizing for large data
StringBuilder sb = new StringBuilder();
// Optimized: Pre-size for 10,000 characters
StringBuilder sb = new StringBuilder(10_000);
sb.append(...); // Fewer reallocations → Faster!
5. Key Optimization Tips
- Avoid Premature Optimization: Use
+
for simple, one-off concatenation (e.g.,"Name: " + name
). - Chain Methods:
sb.append("Name: ").append(name).append(", Age: ").append(age);
- Reuse Builders: Reset with
setLength(0)
to reuse buffers:
sb.setLength(0); // Clear content, keep capacity
Performance Benchmark
Test concatenating 10,000 integers:
Method | Time (ms) | Objects Created |
---|---|---|
+ operator | ~400 | 10,000+ |
StringBuilder | ~1 | 1 |
Common Mistakes
❌ Mixing StringBuilder
and +
in Loops:
// Still creates temporary Strings!
for (String s : list) {
sb.append(s + ", "); // Use sb.append(s).append(", ")
}
❌ Using StringBuffer
Unnecessarily: Sacrifices speed for unneeded thread safety.
FAQ
When should I use String.join()
instead of StringBuilder
?
For simple list concatenation (e.g., CSV):String csv = String.join(", ", list); // Clean and efficient
Does StringBuilder
use the String Pool?
No – its internal buffer is mutable and unrelated to the Pool. (String Pool)