StringBuilder & String Formatting
Strings in Java are immutable, which makes glueing lots of text together with + surprisingly wasteful. Meet StringBuilder for efficient text assembly, and printf / String.format for clean, aligned, professional output.
Learn StringBuilder & String Formatting in our free Java course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a…
Part of the free Java course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
1️⃣ Strings Are Immutable
A String can never be changed after it's created. When you write s = s + "!" , Java doesn't edit the old text — it builds a brand-new String and points s at it. The original is left untouched (and eventually garbage-collected).
💡 Analogy: A String is like a printed page — you can't erase a word on it. To "change" it you photocopy the page, write the new version, and throw the old copy away. Do that a million times in a loop and you've made a million photocopies.
This is usually fine. It only becomes a performance problem when you concatenate inside a large loop, where the cost grows quadratically.
2️⃣ StringBuilder — One Buffer, Many Appends
StringBuilder is a mutable , growable buffer of characters. Instead of creating a new object on every change, append() writes into the same buffer — and it returns the builder itself, so calls can be chained.
Method
What it does
append(x)
Add x to the end (returns the builder)
insert(i, x)
Insert x at index i
delete(a, b)
Remove chars from a to b
reverse()
Reverse the buffer in place
length()
Current number of characters
toString()
Produce the final immutable String
3️⃣ String Formatting With printf and format
Glueing values together with + gets ugly fast, and you can't easily control decimals or alignment. Format specifiers solve that. System.out.printf prints directly; String.format returns the text as a value.
Specifier
Inserts
Example
%s
Any value as text
"Alice"
%d
Whole number
42
%f
Decimal number
19.500000
%.2f
2 decimal places
19.50
%5d
Right-justify width 5
" 42"
%-10s
Left-justify width 10
"Item "
%03d
Zero-pad to 3 digits
009
%,d
Thousands grouping
1,240,000
%%
Literal percent sign
%
%n
Newline (portable)
↵
🧩 Reorder Challenge
Reorder these lines so they build a CSV-style line "a,b,c" with a StringBuilder and print it.
Why: The builder must be created first, then appended to, before toString() can extract the finished text. (The line variable and the printed sb.toString() are equivalent — you'd normally print line .) Output: a,b,c .
🧠 Quick Recall
abc — unchanged! Strings are immutable, so toUpperCase() returns a new String that is thrown away. You must capture it: s = s.toUpperCase(); .
03.50 . Two decimal places, total width 5, zero-padded — "3.50" is 4 chars, so one leading zero fills it to 5.
avaJ . reverse() mutates the builder in place, and printing it implicitly calls toString() .
Common Beginner Mistakes
- ❌ Ignoring the return value: s.replace("a","b"); does nothing useful — assign it: s = s.replace(...) .
- ❌ Concatenating in a big loop: use StringBuilder.append , not + , when the loop is large.
- ❌ Wrong specifier type: %d with a double, or %f with an int, throws an IllegalFormatConversionException .
- ❌ Forgetting %% : a lone % in a format string is an error; use %% for a literal percent.
- ❌ Never calling toString(): a StringBuilder is not a String ; call toString() when you need one.
📋 Quick Reference
Method / Specifier
Description
Example → result
new StringBuilder()
Create an empty buffer
StringBuilder sb = new StringBuilder();
Add to the end; returns the builder
sb.append("a").append("b")
sb.insert(0, ">> ")
Remove chars from a up to b
sb.delete(0, 2)
"Java" → "avaJ"
sb.length()
sb.toString()
Decimal, 2 places
Left-justify in width 10
%% / %n
Literal percent / portable newline
% / ↵
String.format(fmt, ...)
Build a formatted String (vs printf prints it)
String.format("[%03d]", 9) → "[009]"
Frequently Asked Questions
🎉 Lesson Complete!
You now understand why Strings are immutable, when to reach for StringBuilder , and how to produce polished output with printf and String.format — including decimals, padding, alignment, and grouping.
Next up: ArrayList — a resizable, dynamic list that grows and shrinks as you add and remove items.
Practice quiz
What does this print? StringBuilder sb = new StringBuilder("Java"); sb.reverse(); System.out.println(sb);
- Java
- JAVA
- avaJ
- java
Answer: avaJ. reverse() mutates the builder in place to avaJ, and printing it implicitly calls toString().
Why are Java Strings immutable a problem when concatenating in a large loop?
- Each + creates a new String object, making the loop O(n squared) work
- The loop never terminates
- Strings cannot be concatenated at all
- It causes a compile error
Answer: Each + creates a new String object, making the loop O(n squared) work. Because Strings are immutable, each + allocates a brand-new object. In a large loop that quadratic allocation is genuinely slow - StringBuilder fixes it.
What does new StringBuilder().append("a").append(1).append("b").toString() produce?
- "ab"
- "a b"
- "1ab"
- "a1b"
Answer: "a1b". append accepts any value and adds it to the end in order: "a", then 1, then "b" gives "a1b". Calls chain because append returns the builder.
What does System.out.printf("%05.2f%n", 3.5) print?
- 3.50
- 03.50
- 3.5
- 003.5
Answer: 03.50. Two decimal places gives "3.50" (4 chars); width 5 zero-padded adds one leading zero: 03.50.
What is the difference between System.out.printf and String.format?
- printf prints to the console; String.format returns the formatted String as a value
- They use different specifiers
- String.format is faster
- printf returns the String
Answer: printf prints to the console; String.format returns the formatted String as a value. Both use identical specifiers, but printf prints directly while String.format builds and returns the text so you can store or pass it.
What does this print? String s = "abc"; s.toUpperCase(); System.out.println(s);
- ABC
- Abc
- abc
- It throws an exception
Answer: abc. Strings are immutable: toUpperCase() returns a NEW String that is discarded. You must capture it with s = s.toUpperCase().
Which specifier prints a literal percent sign in a format string?
- %
- %%
- \%
- %p
Answer: %%. A lone % starts a specifier, so you write %% to print one literal percent sign.
What does String.format("[%03d]", 9) return?
%03d zero-pads the number to 3 digits, producing "[009]".
When should you reach for StringBuilder instead of +?
- For every single concatenation, always
- When building a string piece by piece, especially inside a loop
- Never - + is always better
- Only for joining exactly two literals
Answer: When building a string piece by piece, especially inside a loop. Use StringBuilder when assembling text in a loop. For a one-off join of two or three literals, plain + is fine and more readable.
Which printf specifier should you prefer for a portable newline?
- %n
- %l
Answer: %n. %n produces a platform-independent newline inside printf, preferred over so output uses the correct line ending on every OS.
Continue this course
- Previous: The Math Class
- Next: ArrayList