Methods, Arrays & Strings

StringBuilder & String Formatting

15 min Lesson 9 of 14

StringBuilder & String Formatting

In the previous lesson you explored the String class and its many useful methods. You may have noticed one quirk: every time you modify a String, Java silently creates a brand-new object in memory. For occasional edits that is fine, but inside a loop — or when building a long text piece by piece — it becomes expensive. This is where StringBuilder steps in. You will also learn String.format and printf, two tools that let you produce polished, structured output without messy concatenation.

Why Strings Are Immutable

String objects in Java are immutable — once created, the characters inside cannot change. When you write:

String result = ""; for (int i = 0; i < 5; i++) { result = result + i; // creates a new String object every iteration } System.out.println(result); // 01234

Java creates six String objects here — one empty, then one for each concatenation. With five iterations that is almost unnoticeable, but with thousands of iterations it wastes significant memory and time.

Immutability is usually a feature. It makes strings safe to share across threads and lets the JVM cache them. The cost only becomes a problem when you concatenate inside tight loops.

StringBuilder: A Mutable Character Buffer

StringBuilder keeps a single resizable character buffer. You modify it in place — no new objects are created for each change. The basic pattern is: create, mutate repeatedly, then call toString() once at the end.

StringBuilder sb = new StringBuilder(); for (int i = 0; i < 5; i++) { sb.append(i); // modifies the same buffer } String result = sb.toString(); System.out.println(result); // 01234

One StringBuilder object instead of six String objects — same output, much less waste.

Key StringBuilder Methods

All mutation methods return this, so you can chain them:

StringBuilder sb = new StringBuilder("Hello"); sb.append(", World"); // Hello, World sb.insert(5, " Beautiful"); // Hello Beautiful, World sb.replace(6, 15, "Java"); // Hello Java, World sb.delete(11, 17); // Hello Java sb.reverse(); // avaJ olleH System.out.println(sb.toString()); // avaJ olleH System.out.println(sb.length()); // 10 System.out.println(sb.charAt(0)); // a
  • append(value) — adds any value (String, int, double, char, boolean, …) to the end.
  • insert(index, value) — inserts at a specific position.
  • replace(start, end, str) — replaces characters from start (inclusive) to end (exclusive).
  • delete(start, end) — removes the characters in that range.
  • reverse() — reverses the entire buffer.
  • length() — current number of characters.
  • toString() — converts the buffer to an ordinary immutable String.
Method chaining keeps code compact. Because every mutating method returns the same StringBuilder, you can write: new StringBuilder().append("A").append("B").append("C").toString() all on one line.

Building a CSV Row — a Practical Example

String[] names = {"Alice", "Bob", "Carol"}; StringBuilder csv = new StringBuilder(); for (int i = 0; i < names.length; i++) { csv.append(names[i]); if (i < names.length - 1) { csv.append(","); } } System.out.println(csv.toString()); // Alice,Bob,Carol

This pattern — accumulate with a StringBuilder, add separators conditionally, call toString() — appears everywhere in real Java code.

String.format — Clean Templated Strings

String.format works like a template engine. You write a format string with placeholders (format specifiers), and the method fills them in:

String name = "Alice"; int age = 30; double score = 92.5; String line = String.format("Name: %s | Age: %d | Score: %.1f%%", name, age, score); System.out.println(line); // Name: Alice | Age: 30 | Score: 92.5%

The most common specifiers:

  • %s — any object, converted via toString().
  • %d — integer (int, long).
  • %f — floating-point; %.2f means two decimal places.
  • %n — platform-correct newline (prefer this over \n in format strings).
  • %% — a literal percent sign.
Width and alignment: %10s right-pads a string in a field of 10 characters; %-10s left-aligns it. Useful for printing tables.

printf — Format and Print in One Step

System.out.printf applies the same format string but prints directly — no intermediate String variable needed:

String[] products = {"Apple", "Banana", "Cherry"}; double[] prices = {1.20, 0.50, 3.75}; System.out.printf("%-10s %8s%n", "Product", "Price"); System.out.printf("%-10s %8s%n", "-------", "-----"); for (int i = 0; i < products.length; i++) { System.out.printf("%-10s %8.2f%n", products[i], prices[i]); }

Output:

Product Price ------- ----- Apple 1.20 Banana 0.50 Cherry 3.75
printf does not append a newline automatically. Always end your format string with %n (or \n) when you want each call on its own line, unlike println which adds one for you.

Choosing the Right Tool

  • Simple, one-time concatenation — the + operator is fine; the compiler optimises it.
  • Building text across many steps or in a loop — use StringBuilder.
  • Producing formatted output (tables, reports, labels) — use String.format or printf.
StringBuffer vs StringBuilder: You may encounter StringBuffer in older code. It is thread-safe but slower. Unless you are sharing a buffer between threads, always prefer StringBuilder.

Summary

String immutability is a feature, not a bug — but it means heavy concatenation in loops wastes memory. StringBuilder gives you a single mutable buffer you can append, insert, delete, and reverse before converting to a String once with toString(). String.format and printf let you embed values into readable templates using format specifiers such as %s, %d, and %.2f, making structured output clean and maintainable. With these tools you can handle nearly every text-building task in Java efficiently.