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

📋 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