Why StringBuilder
Why StringBuilder?
StringBuilder is a mutable alternative to String for efficient string manipulation.
Problem with String Concatenation
// BAD: O(n^2) time complexity
String result = "";
for (int i = 0; i < 10000; i++) {
result += i; // Creates new String each iteration!
}
// Each iteration creates:
// 1. New String for i.toString()
// 2. New String for concatenation
// Total: 10000 * 2 = 20000 String objects!
Solution with StringBuilder
// GOOD: O(n) time complexity
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.append(i); // Modifies existing object
}
String result = sb.toString();
// Only 1 StringBuilder object created!
When to Use StringBuilder
// Use StringBuilder when:
// 1. Multiple concatenations in loop
StringBuilder sb = new StringBuilder();
for (String s : list) {
sb.append(s).append(",");
}
// 2. Building strings incrementally
StringBuilder sb = new StringBuilder();
sb.append("Hello").append(" ").append("World");
// 3. String reversal
String reversed = new StringBuilder(str).reverse().toString();
// 4. Insert/delete operations
StringBuilder sb = new StringBuilder("Hello World");
sb.insert(5, " beautiful"); // "Hello beautiful World"
sb.delete(6, 16); // "Hello World"
// Use String when:
// 1. Simple concatenation (compiler optimizes)
String s = "Hello" + " " + "World";
// 2. Few concatenations
String s = firstName + " " + lastName;
// 3. String is used as map key or in comparisons
Map<String, Integer> map = new HashMap<>();
map.put("hello", 1); // Use String, not StringBuilder
Performance Comparison
// Benchmark: 10000 concatenations
// String: ~500ms
// StringBuilder: ~1ms
// The more concatenations, the bigger the difference
Methods
StringBuilder Methods
Basic Operations
StringBuilder sb = new StringBuilder("Hello");
// Append - adds to end
sb.append(" World"); // "Hello World"
sb.append(123); // "Hello World123"
sb.append(true); // "Hello World123true"
// Insert - adds at position
sb.insert(5, " cruel"); // "Hello cruel World123true"
// Delete - removes characters
sb.delete(5, 11); // "Hello World123true" (removes " cruel")
sb.deleteCharAt(0); // "ello World123true"
// Replace - replaces range
sb.replace(0, 5, "Hi"); // "Hi World123true"
// Reverse
sb.reverse(); // "eurt321dlroW iH"
Access Methods
StringBuilder sb = new StringBuilder("Hello");
// Length
int len = sb.length(); // 5
// Capacity
int cap = sb.capacity(); // 21 (16 + 5)
// Char at
char c = sb.charAt(0); // 'H'
// Index of
int idx = sb.indexOf("ll"); // 2
int idx2 = sb.indexOf("l", 3); // 3 (start searching from index 3)
// Substring
String sub = sb.substring(1, 3); // "el"
String sub2 = sb.substring(2); // "llo"
Modification Methods
StringBuilder sb = new StringBuilder("Hello");
// Set char at
sb.setCharAt(0, 'J'); // "Jello"
// Set length
sb.setLength(3); // "Jel" (truncates)
sb.setLength(10); // "Jel\\0\\0\\0\\0\\0\\0\\0" (pads with null chars)
// Ensure capacity
sb.ensureCapacity(100); // Ensure at least 100 capacity
// Trim to size
sb.trimToSize(); // Reduce capacity to current length
Method Chaining
// StringBuilder methods return this, enabling chaining
StringBuilder sb = new StringBuilder();
sb.append("Hello")
.append(" ")
.append("World")
.insert(5, ",")
.deleteCharAt(6);
// Result: "Hello World"
Converting to String
StringBuilder sb = new StringBuilder("Hello World");
String str = sb.toString(); // "Hello World"
// Important: toString() creates a new String
// After toString(), modifying sb doesn't affect str
Complete Example
public class StringBuilderMethodsDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
// Build a formatted string
sb.append("Name: ").append("Alice").append("\n");
sb.append("Age: ").append(30).append("\n");
sb.append("Active: ").append(true);
String result = sb.toString();
System.out.println(result);
// Output:
// Name: Alice
// Age: 30
// Active: true
}
}
Capacity
Capacity vs Length
StringBuilder has two important properties: length and capacity.
Understanding Capacity
// Default capacity: 16
StringBuilder sb = new StringBuilder();
int len = sb.length(); // 0
int cap = sb.capacity(); // 16
// With initial string
StringBuilder sb2 = new StringBuilder("Hello");
int len2 = sb2.length(); // 5
int cap2 = sb2.capacity(); // 21 (16 + 5)
// With initial capacity
StringBuilder sb3 = new StringBuilder(100);
int len3 = sb3.length(); // 0
int cap3 = sb3.capacity(); // 100
How Capacity Grows
StringBuilder sb = new StringBuilder();
// When capacity is exceeded, it grows:
// New capacity = (old capacity + 1) * 2
// Start: capacity = 16
// After 17 appends: capacity = 34
// After 35 appends: capacity = 70
// And so on...
// This doubling strategy makes appending O(1) amortized
Pre-allocating Capacity
// If you know approximate size, pre-allocate
StringBuilder sb = new StringBuilder(10000);
for (int i = 0; i < 10000; i++) {
sb.append(i);
}
// No reallocation needed!
// Without pre-allocation:
// Would need ~14 reallocations (16 -> 34 -> 70 -> ...)
Capacity Operations
StringBuilder sb = new StringBuilder("Hello");
// Current capacity
int cap = sb.capacity(); // 21
// Ensure minimum capacity
sb.ensureCapacity(100); // Now capacity >= 100
// Trim to fit
sb.trimToSize(); // Capacity = length
Performance Impact
// Bad: Frequent reallocation
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
sb.append("a");
// Multiple reallocations occur
}
// Good: Pre-allocate
StringBuilder sb = new StringBuilder(100000);
for (int i = 0; i < 100000; i++) {
sb.append("a");
// No reallocation
}
When to Use Capacity
// Use default capacity (16) when:
// - String size is unknown or small
// - Building string incrementally with few appends
// Pre-allocate when:
// - Known maximum size
// - Building large strings (JSON, SQL, etc.)
// - Performance-critical code
vs StringBuffer
StringBuilder vs StringBuffer
Both are mutable string builders, but with key differences.
Thread Safety
// StringBuilder: NOT thread-safe
// - No synchronization
// - Faster single-threaded performance
// StringBuffer: Thread-safe
// - All methods are synchronized
// - Slower due to synchronization overhead
// Example:
StringBuilder sb = new StringBuilder();
StringBuffer buf = new StringBuffer();
// Both have same methods
sb.append("Hello");
buf.append("Hello");
When to Use Which
// Use StringBuilder when:
// 1. Single-threaded code
StringBuilder sb = new StringBuilder();
for (String s : list) {
sb.append(s); // No synchronization needed
}
// 2. Local variable (not shared)
public String process(String input) {
StringBuilder sb = new StringBuilder();
// sb is local, not shared
sb.append(input).reverse();
return sb.toString();
}
// Use StringBuffer when:
// 1. Multi-threaded code
public class SharedBuilder {
private StringBuffer buffer = new StringBuffer();
public void append(String s) {
buffer.append(s); // Thread-safe
}
}
// 2. When thread safety is required
// (rare in modern Java)
Performance Comparison
// StringBuilder is faster because:
// - No synchronization overhead
// - No method locking
// Benchmark (100000 concatenations):
// StringBuilder: ~10ms
// StringBuffer: ~15ms
// The difference is small for simple operations
// but can be significant in tight loops
Historical Context
// Java 1.0: Only StringBuffer existed
// Java 1.5: StringBuilder added (not thread-safe)
// Reason: Most string building is single-threaded
// StringBuilder avoids unnecessary synchronization
// Modern Java:
// - StringBuilder is preferred
// - StringBuffer is rarely used
// - Consider StringJoiner or Collectors for stream operations
Summary
| Feature | StringBuilder | StringBuffer |
|---|---|---|
| Thread-safe | No | Yes |
| Performance | Faster | Slower |
| Introduced | Java 1.5 | Java 1.0 |
| Use case | Single-thread | Multi-thread |
| Preferred | Yes | No (rarely) |
Practice Problems
Reverse a string using StringBuilder.
Example:
Input: s = "hello"
Output: "olleh"
Reverse the string
Optimal Solution — O(n) time, O(n) space
Use StringBuilder.reverse() method.
public String reverseString(String s) {
return new StringBuilder(s).reverse().toString();
}Edge Cases:
- Single character
- Empty string
- Already reversed
Compress string using counts of repeated characters (e.g., aabcccccaaa -> a2b1c5a3).
Example:
Input: s = "aabcccccaaa"
Output: "a2b1c5a3"
Compress consecutive characters
Optimal Solution — O(n) time, O(n) space
Use StringBuilder to build compressed string.
public String compressString(String s) {
StringBuilder sb = new StringBuilder();
int count = 1;
for (int i = 1; i <= s.length(); i++) {
if (i < s.length() && s.charAt(i) == s.charAt(i - 1)) {
count++;
} else {
sb.append(s.charAt(i - 1));
sb.append(count);
count = 1;
}
}
return sb.length() < s.length() ? sb.toString() : s;
}Edge Cases:
- All same characters
- No consecutive characters
- Single character
Quiz
1. What is the default capacity of a StringBuilder?
2. When should you use StringBuilder instead of String?
3. What is the difference between StringBuilder and StringBuffer?
4. What is the primary purpose of StringBuilder?
Flashcards
Question
What is StringBuilder?
Click to reveal answer
Answer
A mutable sequence of characters. Unlike String, it can be modified without creating new objects.
Question
How do you convert StringBuilder to String?
Click to reveal answer
Answer
Use toString() method: StringBuilder sb = ...; String str = sb.toString();
Question
What is the time complexity of StringBuilder.append()?
Click to reveal answer
Answer
O(1) amortized. Amortized because occasional resizing is O(n) but happens rarely.
Question
What is StringBuilder?
Click to reveal answer
Answer
StringBuilder is a key concept in Java programming.
Question
When to use StringBuilder?
Click to reveal answer
Answer
Use StringBuilder when building production systems that require reliability, scalability, and maintainability.
Revision Notes
Key Takeaways
- 1.StringBuilder is mutable, String is immutable
- 2.Use StringBuilder for multiple concatenations in loops
- 3.Default capacity is 16, grows by doubling
- 4.StringBuilder is not thread-safe, StringBuffer is
Interview Tips
- •Know when to use StringBuilder vs String
- •Understand capacity and how it grows
- •Remember StringBuilder is not thread-safe
- •Practice string manipulation problems
Cheat Sheet
Cheat Sheet
- Create:
new StringBuilder()ornew StringBuilder("initial") - Append:
sb.append(str) - Insert:
sb.insert(index, str) - Delete:
sb.delete(start, end) - Reverse:
sb.reverse() - Length:
sb.length() - Capacity:
sb.capacity() - To String:
sb.toString()