StringBuilder Class in Java – Fast, Mutable Strings
StringBuilder is a mutable sequence of characters, added in Java 5 as a faster, unsynchronized alternative to StringBuffer. It is the standard tool for building strings piece by piece: in loops, when generating CSV, JSON or HTML, or whenever many modifications are needed. The compiler itself uses similar techniques for the + operator.
This tutorial covers building strings with StringBuilder, its key methods, capacity, comparison pitfalls, and how it compares with String and StringBuffer.
1. Building a String Step by Step
import java.util.List;
public class BuildCsv {
record Employee(String name, String dept, double salary) { }
public static void main(String[] args) {
List<Employee> staff = List.of(new Employee("Asha", "Backend", 120000),
new Employee("Ravi", "Frontend", 95000),
new Employee("Meera", "Data", 130000));
StringBuilder csv = new StringBuilder(128); // pre-size when you can estimate
csv.append("name,dept,salary\n");
for (Employee e : staff) {
csv.append(e.name()).append(',')
.append(e.dept()).append(',')
.append(e.salary()).append('\n'); // chaining
}
System.out.print(csv);
System.out.println("characters: " + csv.length());
}
}
name,dept,salary Asha,Backend,120000.0 Ravi,Frontend,95000.0 Meera,Data,130000.0 characters: 81
append returns the same builder, so calls chain naturally. Call toString() (or pass the builder where a CharSequence is accepted, as print does) to get the result.
2. Key Methods
public class BuilderMethods {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("racecar level noon");
System.out.println("reverse() : " + new StringBuilder("Java").reverse());
System.out.println("insert(0, \">\") : " + new StringBuilder("menu").insert(0, "> "));
sb.replace(0, 7, "kayak");
System.out.println("replace : " + sb);
sb.delete(5, 11);
System.out.println("delete : " + sb);
sb.setLength(0); // clear and reuse
System.out.println("after setLength(0), isEmpty(): " + sb.isEmpty());
String word = "madam";
boolean palindrome = new StringBuilder(word).reverse().toString().equals(word);
System.out.println(word + " is a palindrome: " + palindrome);
StringBuilder a = new StringBuilder("abc"), b = new StringBuilder("abc");
System.out.println("a.equals(b) : " + a.equals(b)); // identity!
System.out.println("a.compareTo(b) == 0: " + (a.compareTo(b) == 0)); // Java 11
System.out.println("contentEquals : " + "abc".contentEquals(a));
}
}
reverse() : avaJ insert(0, ">") : > menu replace : kayak level noon delete : kayak noon after setLength(0), isEmpty(): true madam is a palindrome: true a.equals(b) : false a.compareTo(b) == 0: true contentEquals : true
| Method | Purpose |
|---|---|
append(x) | Add a value of any type at the end |
insert(i, x) | Insert at an index |
replace(start, end, s) | Replace a range |
delete(start, end), deleteCharAt(i) | Remove characters |
reverse() | Reverse in place (handles surrogate pairs correctly) |
setLength(n) | Truncate, or clear with setLength(0) to reuse the builder |
charAt, setCharAt, indexOf, substring | Read, write and search |
capacity(), ensureCapacity(), trimToSize() | Manage the internal buffer |
compareTo() (11), isEmpty() (15), repeat() (21) | Newer conveniences |
Pitfall: StringBuilder does not override equals(), so two builders with the same text are not equal. Compare with compareTo, String.contentEquals, or their toString() values.
3. Capacity
Like StringBuffer, a builder starts with a capacity of 16 (or 16 + initial text length) and grows to (old × 2 + 2) when needed, copying its contents. If you can estimate the final size, pass it to the constructor, as new StringBuilder(128) above, to avoid repeated copying. See StringBuffer for a capacity demonstration.
4. Performance: String vs StringBuffer vs StringBuilder
public class PerformanceCompare {
static long time(Runnable r) {
long start = System.nanoTime();
r.run();
return (System.nanoTime() - start) / 1_000_000;
}
public static void main(String[] args) {
int n = 50_000;
long concat = time(() -> { String s = ""; for (int i = 0; i < n; i++) s += i % 10; });
long buffer = time(() -> { StringBuffer s = new StringBuffer(); for (int i = 0; i < n; i++) s.append(i % 10); });
long builder = time(() -> { StringBuilder s = new StringBuilder(); for (int i = 0; i < n; i++) s.append(i % 10); });
System.out.println("String += is the slowest: " + (concat > buffer && concat > builder));
System.out.printf("String += %5d ms%nStringBuffer %5d ms%nStringBuilder %5d ms%n", concat, buffer, builder);
}
}
String += is the slowest: true String += 83 ms StringBuffer 1 ms StringBuilder 0 ms
Repeated += copies the whole string on every iteration (quadratic time). Both builders append in place; StringBuilder avoids synchronization overhead as well.
| Aspect | String | StringBuffer | StringBuilder |
|---|---|---|---|
| Mutable | No | Yes | Yes |
| Synchronized | Not needed | Yes | No |
| Speed for repeated changes | Slow | Fast | Fastest |
| Use when | Value does not change | One instance shared across threads | Building strings in one thread (most cases) |
5. When to Use StringBuilder
- Concatenating inside loops.
- Building text conditionally across several statements.
- Manipulating characters: reversing, inserting, deleting.
You do not need it for a single expression like "Hello " + name + "!"; the compiler optimises that. For joining with separators, StringJoiner, String.join or Collectors.joining are clearer.
6. Summary
StringBuilderis a mutable, unsynchronized character sequence for efficient string building.- Use
append,insert,replace,deleteandreverse, thentoString(). - It does not override
equals; compare contents explicitly. - Prefer it over
+=in loops and overStringBufferunless an instance is shared between threads.
Related Tutorials
Frequently Asked Questions (FAQ)
Q1. What is StringBuilder in Java?
A mutable, non-synchronized sequence of characters used to build and modify strings efficiently.
Q2. What is the difference between StringBuilder and StringBuffer?
Both are mutable with the same methods, but StringBuffer is synchronized and StringBuilder is not, making StringBuilder faster for single-threaded use.
Q3. Is StringBuilder thread-safe?
No. Do not share one instance between threads without external synchronization.
Q4. Why use StringBuilder instead of String concatenation?
Concatenating in a loop with + creates a new string each time. StringBuilder modifies one buffer, giving much better performance.
Q5. Does the compiler use StringBuilder for +?
Before Java 9 it compiled + to StringBuilder calls. Since Java 9 it uses invokedynamic with StringConcatFactory, which is similarly efficient for single expressions.
Q6. What is the default capacity of StringBuilder?
16 characters, or 16 plus the length of the initial string.
Q7. How do I clear a StringBuilder?
Call setLength(0), which keeps the allocated capacity for reuse.
Q8. How do I reverse a String using StringBuilder?
new StringBuilder(text).reverse().toString().
Q9. How do I compare two StringBuilders?
Use sb1.compareTo(sb2) == 0 (Java 11+) or sb1.toString().equals(sb2.toString()); equals() compares references.
Q10. Is StringBuilder final?
Yes, it cannot be subclassed.
Q11. Can StringBuilder hold null?
append(null) appends the text "null". Passing null to the constructor throws NullPointerException.
Q12. What does insert() do?
It inserts the string form of a value at the given index, shifting later characters to the right.
Q13. What is the difference between delete() and deleteCharAt()?
delete(start, end) removes a range; deleteCharAt(i) removes a single character.
Q14. Which interfaces does StringBuilder implement?
CharSequence, Appendable, Serializable and Comparable<StringBuilder> (Java 11).
Q15. Should I pre-size a StringBuilder?
If you can estimate the final length, yes; it avoids repeated array copying. Otherwise the default growth is usually fine.
Q16. How does StringBuilder handle Unicode?
It stores UTF-16 code units. reverse() keeps surrogate pairs intact, and appendCodePoint adds characters outside the Basic Multilingual Plane.
Q17. Can I use StringBuilder in a stream?
Usually Collectors.joining() is simpler. A StringBuilder can be used with collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).
Q18. What happens with an invalid index?
Methods throw StringIndexOutOfBoundsException (or IndexOutOfBoundsException).
Q19. When was StringBuilder introduced?
In Java 5 (JDK 1.5).
Q20. Is StringBuilder faster than StringJoiner?
StringJoiner uses similar techniques internally. Choose based on readability: StringJoiner for delimited lists, StringBuilder for general building.