StringBuilder in Java
Introduction
In Java, String objects are immutable. This means once a String is created, it cannot be changed. Whenever you concatenate or modify a string using the + operator, the JVM actually creates a completely new String object in memory and discards the old one.
In loops or heavy text-processing applications, this leads to massive memory overhead and slow performance. This is where StringBuilder comes in.
1. What is StringBuilder?
StringBuilder is a mutable sequence of characters. It acts as a resizable array for characters, allowing you to append, insert, delete, or modify characters without creating new objects every time.
Basic Usage
public class StringBuilderExample {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello");
// Append modifies the existing object
sb.append(" World");
sb.append("!");
// Convert back to an immutable String
String result = sb.toString();
System.out.println(result); // "Hello World!"
}
}
2. Why use StringBuilder? (The Performance Argument)
Consider the following bad practice:
// BAD PRACTICE
String str = "";
for (int i = 0; i < 10000; i++) {
str += i; // Creates 10,000 new String objects!
}
This requires quadratic time complexity because with every iteration, the entire existing string must be copied into a new memory location along with the new character.
The Fix
// GOOD PRACTICE
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.append(i); // Modifies the internal array
}
String str = sb.toString();
This executes in time complexity, drastically reducing memory allocations and CPU cycles.
3. Internal Mechanics: How does it scale?
Internally, StringBuilder maintains a char[] (or byte[] in modern Java versions via Compact Strings).
When you instantiate it:
StringBuilder sb = new StringBuilder();
It creates an array with a default capacity of 16 characters.
When you append characters and exceed this capacity, StringBuilder must resize its internal array. The standard resizing formula used by the JVM is:
New Capacity = (Old Capacity * 2) + 2
It creates a new, larger array, copies the old characters over, and discards the small array. If you know you are going to append a massive amount of text, you can optimize by setting an initial capacity:
// Allocates an array of 10,000 chars upfront, avoiding resizing overhead
StringBuilder sb = new StringBuilder(10000);
4. Key Methods
append(anyType): Appends the string representation of an argument.insert(int offset, anyType): Inserts data at a specific index.delete(int start, int end): Removes a sequence of characters.reverse(): Reverses the sequence of characters.setCharAt(int index, char ch): Replaces a single character.
Example:
StringBuilder sb = new StringBuilder("Java Programming");
sb.insert(5, "Awesome ");
System.out.println(sb); // "Java Awesome Programming"
sb.reverse();
System.out.println(sb); // "gnimmargorP emosewA avaJ"
5. StringBuilder vs. StringBuffer
You might occasionally see StringBuffer in legacy code.
StringBufferis thread-safe (synchronized). Multiple threads can safely modify it, but it is slower due to locking overhead.StringBuilder(introduced in Java 1.5) is not thread-safe. It is significantly faster and is the preferred choice for 99% of use cases since string manipulation is usually done within a single thread's scope.
Summary
- Strings are immutable; using
+in loops destroys performance. - Use
StringBuilderwhenever concatenating multiple strings dynamically. StringBuilderis mutable, fast, and uses a resizable internal character array.- Prefer
StringBuilderoverStringBufferunless thread-safety is strictly required.