Java course menu
Java StringBuilder: Building Strings Efficiently
Learn when and how to use StringBuilder in Java: why string concatenation in loops is slow, append, insert, delete, reverse, setCharAt, converting with toString, chaining, and StringBuilder vs StringBuffer vs String.
On this page
Because String objects are immutable, every + creates a new string. That is fine for a few joins, but building a long string piece by piece in a loop creates a new string on every iteration and copies all the text so far each time. StringBuilder is a mutable sequence of characters designed for exactly this job.
Building a string in a loop#
public class Main {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 5; i++) {
sb.append(i);
if (i < 5) sb.append(", ");
}
String result = sb.toString();
System.out.println(result);
}
}1, 2, 3, 4, 5append adds to the end of the same builder, with no new string per step. Call toString() at the end to get an ordinary String.
Why it matters#
Concatenating with += in a loop has to copy the whole string so far on each step, which takes O(n²) time in total. StringBuilder grows its internal buffer as needed, so the total is O(n). The difference is invisible for 10 pieces, and dramatic for 100,000:
public class Main {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100_000; i++) {
sb.append('x');
}
System.out.println(sb.length());
}
}100000The same loop with String s = ""; s += 'x'; does the same thing, but copies billions of characters along the way.
The main methods#
public class Main {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello World");
sb.append("!"); // Hello World!
sb.insert(5, ","); // Hello, World!
sb.replace(7, 12, "Java"); // Hello, Java!
System.out.println(sb);
sb.delete(5, 6); // Hello Java!
sb.deleteCharAt(sb.length() - 1);
sb.setCharAt(0, 'J');
System.out.println(sb);
System.out.println(sb.reverse());
System.out.println(sb.length() + " " + sb.indexOf("o"));
}
}Hello, Java!
Jello Java
avaJ olleJ
10 5Chaining#
Most methods return the builder itself, so calls can be chained:
public class Main {
public static void main(String[] args) {
String receipt = new StringBuilder()
.append("Item: ").append("Notebook").append('\n')
.append("Qty: ").append(4).append('\n')
.append("Total: ").append(4 * 45.5)
.toString();
System.out.println(receipt);
}
}Item: Notebook
Qty: 4
Total: 182.0Reversing a string#
StringBuilder.reverse() is the standard one-liner:
public class Main {
public static void main(String[] args) {
String word = "stressed";
String reversed = new StringBuilder(word).reverse().toString();
System.out.println(reversed);
}
}dessertsWhen the compiler helps#
For a single expression like "Hello, " + name + "!", the compiler already generates efficient code, so you do not need a StringBuilder there. Use it when you build a string across many statements, especially in loops. For joining a collection with a separator, String.join or a stream's Collectors.joining is even simpler.
StringBuilder vs StringBuffer vs String#
Use StringBuilder in new code; StringBuffer is an older, synchronized version you will rarely need.
Common mistakes#
Practice#
Practice exercise
Using a StringBuilder, build the string "1-2-3-...-10" (the numbers 1 to 10 separated by dashes) and print it, then print the same string reversed.
Show solution
public class Dashes {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 10; i++) {
if (i > 1) sb.append('-');
sb.append(i);
}
System.out.println(sb);
System.out.println(sb.reverse());
}
}1-2-3-4-5-6-7-8-9-10
01-9-8-7-6-5-4-3-2-1reverse works on characters, so 10 becomes 01.
Key takeaway#
Finished this lesson?