Java StringBuilder
Table of Contents + −
In the last lesson you learned about Java string comparison. A String can never change, so building text in a loop with + creates a new String every time and gets slow. Java’s answer is the StringBuilder, a String-like tool you can change in place.
🤔 Why not just use String?
Building a long line in a loop with + is wasteful. Here is the problem.
This loop joins the numbers 1 to 1000 into one String using +.
String result = "";for (int i = 1; i <= 1000; i++) { result = result + i + " "; // ❌ makes a brand new String every single time}A String is immutable, so result + i cannot edit the old String. Every pass Java must:
- Create a new String object.
- Copy all the old characters into it.
- Add the new piece on the end, then throw the old String away.
The work grows as the text grows. By pass 500 it recopies a long line just to add a couple of characters. So 1000 passes means hundreds of throwaway objects and slow, wasteful copying.
A StringBuilder fixes this. It keeps one changeable buffer of characters, so adding text just extends that same buffer. No recopying, no pile of throwaway objects.
Why String can't just change
String is immutable on purpose. Strings get shared and reused all over a program, so making them unchangeable keeps that sharing safe. StringBuilder is the opposite: it is meant to be your private scratch space while you build, not something to share around.
🧱 Creating a StringBuilder
You make a StringBuilder with new. Start it empty or hand it some text.
StringBuilder sb = new StringBuilder(); // starts emptyStringBuilder greeting = new StringBuilder("Hello"); // starts with text insidesbis an empty, changeable text buffer;greetingalready holds “Hello”.- You can keep adding to both without Java making a new object each time.
- Think of a StringBuilder like a whiteboard: write, rub out, add more on the same board. A String is ink on paper, set once and done.
➕ Building text with append
append() is the method you will use most. It adds text to the end of the same builder, in place, and you can chain many appends in one line.
This builds “Hello World” by appending three pieces to one builder.
StringBuilder sb = new StringBuilder();sb.append("Hello");sb.append(" ");sb.append("World");
System.out.println(sb.toString()); // turn it into a real String to printHere is how it works:
- Each
appendadds to the same builder, so no new objects are made. toString()at the end turns the builder into a normal String for printing.appendtakes more than text: Strings, numbers (append(42)), achar, aboolean, even another object. Java turns each into text for you.
Output
Hello WorldYou can chain appends like sb.append(a).append(b) because each append returns the same builder, ready for the next call.
🔁 The loop, done right
Here is that loop again, the proper way, with a StringBuilder. We print just 5 numbers, but picture it running 1000 times.
This builds a line of numbers using one builder and chained appends.
public class BuildLine { public static void main(String[] args) { StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 5; i++) { sb.append(i).append(" "); // ✅ chained appends, same buffer every time }
String result = sb.toString(); System.out.println(result); }}The difference from the + version:
- Each number and space appends to the same builder, so no old text is copied each pass. The text grows in place.
sb.append(i).append(" ")chains two appends, since each returns the builder.toString()hands us the finished String once, not a thousand times.
Output
1 2 3 4 5For 5 numbers you would not notice. The win shows up with large counts: thousands of + passes are much slower. The rule is easy: building text in a loop means StringBuilder.
🛠️ Other useful methods
A StringBuilder can edit text in other ways too. All of these change the builder directly, with no new object made.
This shows insert, append, and reverse on one builder, then replace on another.
StringBuilder sb = new StringBuilder("Hello");
sb.insert(0, ">> "); // add text at a position, push the rest rightsb.append(" World"); // add to the endsb.reverse(); // flip the whole thingSystem.out.println(sb.toString());
StringBuilder name = new StringBuilder("Java");name.replace(0, 1, "L"); // replace index 0 up to (not including) 1 with "L"System.out.println(name.toString());Method by method:
insert(0, ">> ")puts text at index 0, sliding the rest right.append(" World")adds to the end.reverse()flips every character, so the line runs backwards.replace(0, 1, "L")swaps index 0 up to (not including) 1 with “L”, turning “Java” into “Lava”.
Output
dlroW olleH >>LavaThere are removal methods too. This deletes a range of characters, then a single one.
StringBuilder code = new StringBuilder("ABCDEF");
code.delete(1, 3); // remove index 1 up to (not including) 3 -> removes "BC"System.out.println(code.toString()); // ADEF
code.deleteCharAt(0); // remove the single character at index 0System.out.println(code.toString()); // DEFdelete(start, end)removes a whole range.deleteCharAt(index)removes just one character.- Like
replace,deleteuses the “up to but not including the end” rule.
Output
ADEFDEFTwo read methods come up a lot: length() counts the characters inside, and setLength() trims or pads the builder.
StringBuilder text = new StringBuilder("Hello World");
System.out.println(text.length()); // 11 characters right now
text.setLength(5); // cut it down to the first 5 charactersSystem.out.println(text.toString()); // HellosetLength(5)keeps the first 5 characters and drops the rest.setLength(0)empties the builder so you can reuse it.
Output
11HelloHere are the methods you will reach for most.
| Method | What it does |
|---|---|
| append(x) | Adds x to the end |
| insert(i, x) | Inserts x at index i |
| delete(start, end) | Removes characters from start up to end |
| deleteCharAt(i) | Removes the one character at index i |
| replace(start, end, x) | Replaces that range with x |
| reverse() | Flips all the characters |
| length() | How many characters are inside |
| setLength(n) | Trims or pads to n characters |
| toString() | Gives back a normal String |
📦 A quick word on capacity
You may hear the word capacity with StringBuilder. It is simple:
- The builder reserves extra room so it does not grow on every append.
length()is how many characters you have;capacity()is the room set aside right now.- Append past the capacity and Java enlarges the buffer and copies the contents over, the same work the
+loop did, but rarely, not every pass.
You do not manage capacity by hand for normal code. For a huge build, hint the starting size to skip some grow steps.
This starts a builder with room for 1000 characters up front.
StringBuilder big = new StringBuilder(1000); // reserve room for ~1000 charsThat is a small optimization. Most code can ignore capacity and just append.
⚖️ String vs StringBuilder: which to use
The rule is about how often the text changes.
- Use a String for fixed or rarely changed text: names, labels, messages, a few joins. Simpler and safe to share.
- Use a StringBuilder when you build or change text many times, especially in a loop. It avoids throwaway objects, so it is much faster.
- For a couple of
+joins, a String is fine and clearer. Save StringBuilder for heavy, repeated building.
The simple test
Ask yourself: does this text get built up over many steps, or is it set once? Built over many steps, especially in a loop, means StringBuilder. Set once means a plain String.
There is also a close cousin, StringBuffer:
- Same job, same methods as StringBuilder.
- It is thread-safe, so many threads can share one buffer safely; that check makes it a little slower.
- Prefer
StringBuilderfor normal single-threaded code; useStringBufferonly when several threads truly share one buffer.
⚠️ Common Mistakes
A few StringBuilder slip-ups to watch for.
Using + in a big loop. This is the whole reason StringBuilder exists. In a heavy loop, + creates a throwaway String every pass.
// ❌ slow: a new String every passString out = "";for (int i = 0; i < 100000; i++) out = out + i;
// ✅ fast: one bufferStringBuilder sb = new StringBuilder();for (int i = 0; i < 100000; i++) sb.append(i);String out = sb.toString();Forgetting toString(). A StringBuilder is not a String. To store it in a String variable or print it as clean text, call toString().
StringBuilder sb = new StringBuilder("Hi");
// ❌ this is a StringBuilder, not the text you want to keepString text = sb; // won't even compile
// ✅ convert it firstString text2 = sb.toString();Expecting String methods on it. A StringBuilder does not have the full String toolbox, and its equals does not compare text. Convert to a String when you want String methods.
StringBuilder a = new StringBuilder("Hi");StringBuilder b = new StringBuilder("Hi");
// ❌ equals here compares the objects, not the text -> falseSystem.out.println(a.equals(b));
// ✅ compare the text by converting firstSystem.out.println(a.toString().equals(b.toString())); // trueequals does not compare text
StringBuilder.equals() does not look at the characters inside. It checks if the two are the very same object. To compare the contents, call toString() on both and compare those Strings.
✅ Best Practices
Habits for using StringBuilder well.
- Reach for it in loops. Whenever you build text across many passes, use a StringBuilder, not
+. - Chain your appends.
sb.append(a).append(b)reads cleanly and avoids extra lines. - Call
toString()at the end. Convert to a String once, after you finish building. - Reuse a builder with
setLength(0)if you need to start fresh inside the same method instead of making a new one. - Hint the size for huge builds with
new StringBuilder(1000)when you already know it will be big. - Keep String for simple text. Do not over-engineer. A couple of joins do not need a builder.
🧩 What You’ve Learned
Let’s recap StringBuilder.
- ✅ A StringBuilder is a changeable text buffer, unlike the immutable String.
- ✅ It avoids creating throwaway Strings when you build text repeatedly, so it is faster in loops.
- ✅
append()adds to the end and can be chained;insert,delete,deleteCharAt,replace, andreverseedit in place. - ✅
length(),setLength(), andcapacity()help you size and trim the buffer. - ✅ Call
toString()to turn the builder into a normal String. - ✅ StringBuffer does the same job but is thread-safe and a bit slower; prefer StringBuilder for normal code.
- ✅ Use String for fixed text and StringBuilder for heavy, repeated building.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
Why is StringBuilder faster than String for building text in a loop?
Why: String is immutable, so each + makes a new object; StringBuilder edits one buffer in place.
- 2
What does the append() method do?
Why: append adds text to the end of the same StringBuilder object.
- 3
How do you turn a StringBuilder into a normal String?
Why: toString() converts the builder's contents into a String.
- 4
When is a plain String the better choice?
Why: For simple, fixed text a String is clearer; StringBuilder is for heavy repeated building.
🚀 What’s Next?
You now know StringBuilder, the fast changeable way to build text. Next comes its thread-safe cousin, StringBuffer. It does the same job with the same methods, but it is built so many threads can share one buffer safely. Let’s look at it next.