Java
StringBuilder
prepend strings
programming
tutorial

How can we prepend strings with StringBuilder?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Java StringBuilder is designed for mutable string construction, but it does not have a dedicated prepend method. The normal solution is to call insert(0, value). That works well for occasional front insertions, but repeated prepends have a real performance cost because existing characters must shift to the right.

Use insert(0, ...) to Prepend

The direct pattern is simple:

java
1public class Main {
2    public static void main(String[] args) {
3        StringBuilder builder = new StringBuilder("world");
4        builder.insert(0, "hello ");
5
6        System.out.println(builder);
7    }
8}

Output:

text
hello world

insert works at any position. Index 0 means "before the current first character," which is exactly what prepend means.

insert Works for More Than Strings

Like append, insert is overloaded for several types.

java
1public class Main {
2    public static void main(String[] args) {
3        StringBuilder builder = new StringBuilder("items");
4
5        builder.insert(0, 3);
6        builder.insert(1, ' ');
7        builder.insert(0, "Total: ");
8
9        System.out.println(builder);
10    }
11}

Output:

text
Total: 3 items

That makes insert flexible enough for mixed prefixes without forcing you to convert everything to strings first.

Understand the Cost of Repeated Prepends

Appending is cheap because new characters usually go at the end. Prepending is different. Every insert(0, ...) has to move the existing contents to make room.

Example:

java
1public class Main {
2    public static void main(String[] args) {
3        StringBuilder builder = new StringBuilder();
4
5        for (int i = 0; i < 5; i++) {
6            builder.insert(0, i + " ");
7        }
8
9        System.out.println(builder);
10    }
11}

This is perfectly fine for small workloads. But if you do it thousands of times in a loop, the repeated shifting becomes expensive.

Better Patterns for Many Front Insertions

If the algorithm naturally builds content from the front many times, consider a different structure.

One option is to collect parts in a deque and append them once at the end:

java
1import java.util.ArrayDeque;
2import java.util.Deque;
3
4public class Main {
5    public static void main(String[] args) {
6        Deque<String> parts = new ArrayDeque<>();
7        parts.addFirst("world");
8        parts.addFirst("hello ");
9
10        StringBuilder builder = new StringBuilder();
11        for (String part : parts) {
12            builder.append(part);
13        }
14
15        System.out.println(builder);
16    }
17}

This avoids repeated shifting in the builder itself.

Another option is to append in the cheap direction and reverse once at the end, but that is safe only when reversing the full character sequence still produces the intended final text. That is often too fragile for general string building.

Capacity Still Helps

If you know the approximate final size, giving StringBuilder enough initial capacity reduces buffer resizing.

java
StringBuilder builder = new StringBuilder(128);
builder.insert(0, "prefix:");

Capacity planning does not eliminate the cost of shifting existing characters during a prepend, but it does avoid extra reallocations while the buffer grows.

Choose the Tool Based on the Workload

For occasional prepends, insert(0, ...) is the right answer because it is direct and readable. If the code is performance-sensitive and prepends happen at scale, the right answer may be to change the algorithm rather than forcing StringBuilder into a workload it does not handle cheaply.

That is the real lesson: StringBuilder supports prepending, but the data-shape still matters.

Common Pitfalls

  • Looking for a nonexistent prepend method instead of using insert(0, ...).
  • Assuming prepending is as cheap as appending.
  • Using insert(0, ...) inside a large loop without reconsidering the data structure.
  • Treating reverse() as a universal optimization when it may change the intended text.
  • Forgetting that initial capacity affects resizing but not the core shift cost of prepending.

Summary

  • Prepend with StringBuilder by calling insert(0, value).
  • 'insert supports more than just string arguments.'
  • Occasional prepends are fine, but repeated front insertions can be expensive.
  • For many prefixes, collecting parts first is often a better design.
  • Pick the solution based on the actual workload, not only on API availability.

Course illustration
Course illustration

All Rights Reserved.