StringBuilder in Java
-
Last Updated: February 1, 2025
-
By: javahandson
-
Series
A StringBuilder in Java is a class used to create and manipulate mutable sequences of characters. Unlike mutable String, StringBuilder allows modifications to its contents without creating a new object every time a change is made. This makes it more efficient for scenarios where a lot of string manipulation, such as appending, deleting, or inserting characters is required.
StringBuilder objects are mutable, meaning their content can be changed after creation. Unlike String, modifications like appending or replacing characters do not create a new object.
package com.java.handson.strings; public class StringBuilderDemo { public static void main(String[] args) { String str = "Java"; System.out.println("Memory location of str: " + Integer.toHexString(System.identityHashCode(str))); str += " HandsOn"; // Creates a new String object System.out.println("Memory location of str: " + Integer.toHexString(System.identityHashCode(str))); System.out.println(str); StringBuilder stringBuilder = new StringBuilder("Java"); System.out.println("Memory location of stringBuilder: " + Integer.toHexString(System.identityHashCode(str))); stringBuilder.append(" HandsOn"); // Modifies the same StringBuffer object System.out.println("Memory location of stringBuilder: " + Integer.toHexString(System.identityHashCode(str))); System.out.println(stringBuilder); } } Output: Memory location of str: 16d3586 Memory location of str: 154617c Java HandsOn Memory location of stringBuilder: 154617c Memory location of stringBuilder: 154617c Java HandsOn
In the above program, we can see str points to different memory locations when a new string is appended whereas in the case of StringBuilder, the same object gets modified and prints the same memory location.
StringBuilder is not synchronized, which means it is not thread-safe. Multiple threads working on the same StringBuilder object can lead to data corruption. However, this also makes StringBuilder faster compared to StringBuffer which is synchronized.
In the below program, we will see what happens if multiple threads try to update the same StringBuilder object.
package com.java.handson.strings; public class StringBuilderDemo { public static void main(String[] args) { // Shared StringBuilder instance StringBuilder sb = new StringBuilder("Java"); // Thread 1: Appends to the StringBuilder Thread thread1 = new Thread(() -> { for (int i = 0; i < 3; i++) { sb.append(" HandsOn"); System.out.println("Thread 1: " + sb); } }); // Thread 2: Reverses the StringBuilder Thread thread2 = new Thread(() -> { for (int i = 0; i < 3; i++) { sb.reverse(); System.out.println("Thread 2: " + sb); } }); // Start both threads thread1.start(); thread2.start(); } } Output: Thread 1: Java HandsOn Thread 1: nOsdnaH avaJ HandsOn Thread 1: nOsdnaH avaJ HandsOn HandsOn Thread 2: nOsdnaH avaJ Thread 2: nOsdnaH nOsdnaH Java HandsOn Thread 2: nOsdnaH avaJ HandsOn HandsOn
In the above example, multiple threads are trying to update the same StringBuilder object and as we know StringBuilder is not synchronized hence it leads to data corruption and we are seeing uneven output.
Now we will rewrite the above program where the append and reverse operations are synchronized for thread safety.
package com.java.handson.strings; public class StringBuilderDemo { public static void main(String[] args) { // Shared StringBuilder instance StringBuilder sb = new StringBuilder("Java"); // Thread 1: Appends to the StringBuilder Thread thread1 = new Thread(() -> { synchronized (sb) { for (int i = 0; i < 3; i++) { sb.append(" HandsOn"); System.out.println("Thread 1: " + sb); } } }); // Thread 2: Reverses the StringBuilder Thread thread2 = new Thread(() -> { synchronized (sb) { for (int i = 0; i < 3; i++) { sb.reverse(); System.out.println("Thread 2: " + sb); } } }); // Start both threads thread1.start(); thread2.start(); } } Output: Thread 1: Java HandsOn Thread 1: Java HandsOn HandsOn Thread 1: Java HandsOn HandsOn HandsOn Thread 2: nOsdnaH nOsdnaH nOsdnaH avaJ Thread 2: nOsdnaH nOsdnaH nOsdnaH avaJ Thread 2: nOsdnaH nOsdnaH nOsdnaH avaJ
In the above program, the output will switch between the threads in an orderly manner, ensuring consistency without any corruption.
StringBuilder manages its capacity dynamically. If the number of characters exceeds the current capacity, it automatically expands to accommodate more characters. We can use the ensureCapacity() method to manage this explicitly.
StringBuilder is more efficient for frequent modifications like concatenation, insertion, or deletion compared to String, which creates new objects for every change.
StringBuilder methods like append(), insert(), delete(), etc., return the same StringBuilder object, allowing method chaining for cleaner and more concise code.
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World").insert(6, "Java ").reverse();
System.out.println(sb); // Output: dlroW avaJ olleH
1. StringBuilder() – Creates an empty StringBuilder with an initial capacity of 16 characters.
StringBuilder sb = new StringBuilder();
sb.append("Java");
System.out.println(sb.capacity()); // Output: 16
2. StringBuilder(int capacity) – Creates an empty StringBuilder with the specified initial capacity.
StringBuilder sb = new StringBuilder(50);
sb.append("Java");
System.out.println(sb.capacity()); // Output: 50
3. StringBuilder(String str) – Creates a StringBuilder with an initial content of the specified string and a capacity of the length of the string + 16.
StringBuilder sb = new StringBuilder("Java");
System.out.println(sb.capacity()); // Output: 20
4. StringBuilder(CharSequence seq) – Creates a StringBuilder with an initial content of the specified CharSequence (e.g., String, StringBuffer, etc.).
CharSequence seq = "Java HandsOn";
StringBuilder sb = new StringBuilder(seq);
System.out.println(sb); // Output: Java HandsOn
The StringBuilder class provides several methods to perform operations like modifying, appending, deleting, and reversing strings. Here are some of the most commonly used methods of StringBuilder:
1. append(String str) – Appends the specified string to the end of the current StringBuilder.
StringBuilder sb = new StringBuilder("Java");
sb.append(" HandsOn");
System.out.println(sb); // Output: Java HandsOn
2. insert(int offset, String str) – Inserts the specified string at the given index.
StringBuilder sb = new StringBuilder("Java");
sb.insert(2, "HandsOn");
System.out.println(sb); // Output: JaHandsOnva
3. replace(int start, int end, String str) – Replace the characters in the specified range with the given string.
StringBuilder sb = new StringBuilder("Java Hello");
sb.replace(5, 10, "HandsOn");
System.out.println(sb); // Output: Java HandsOn
4. delete(int start, int end) – Removes the characters in the specified range.
StringBuilder sb = new StringBuilder("Java HandsOn");
sb.delete(5, 10);
System.out.println(sb); // Output: Java On
5. deleteCharAt(int index) – Removes the character at the specified index.
StringBuilder sb = new StringBuilder("Java H");
sb.deleteCharAt(4);
System.out.println(sb); // Output: JavaH
6. reverse() – Reverses the sequence of characters in the StringBuilder.
StringBuilder sb = new StringBuilder("Java HandsOn");
sb.reverse();
System.out.println(sb); // Output: nOsdnaH avaJ
7. charAt(int index) – Returns the character at the specified index.
StringBuilder sb = new StringBuilder("Java HandsOn");
System.out.println(sb.charAt(5)); // Output: H
8. setCharAt(int index, char ch) – Sets the character at the specified index.
StringBuilder sb = new StringBuilder("Java H");
sb.setCharAt(5, 'J');
System.out.println(sb); // Output: Java J
9. capacity() – Returns the current capacity of the StringBuilder.
StringBuilder sb = new StringBuilder("Java");
System.out.println(sb.capacity()); // Output: 20 (length + 16)
10. length() – Returns the number of characters in the StringBuilder.
StringBuilder sb = new StringBuilder("Java HandsOn");
System.out.println(sb.length()); // Output: 12
11. setLength(int newLength) – Sets the length of the StringBuilder. If the new length is less than the current length it truncates the builder but if it’s more then it pads with null (\u0000).
StringBuilder sb = new StringBuilder("Java HandsOn");
sb.setLength(4);
System.out.println(sb); // Output: Java
sb.setLength(6);
System.out.println(sb); // Output: Java\u0000\u0000
12. substring(int start) – Extracts a complete substring from the specified range.
StringBuilder sb = new StringBuilder("Java HandsOn");
System.out.println(sb.substring(5)); // Output: HandsOn
13. substring(int start, int end) – Extracts a substring from a range that includes start but excludes end.
StringBuilder sb = new StringBuilder("Java HandsOn");
System.out.println(sb.substring(0, 4)); // Output: Java
14. ensureCapacity(int minimumCapacity) – Ensures that the StringBuilder has at least the specified capacity.
StringBuilder sb = new StringBuilder();
sb.ensureCapacity(50);
System.out.println("Capacity: " + sb.capacity()); // Output: 50
15. indexOf(String str) – Returns the index of the first occurrence of the specified string starting from the beginning index.
StringBuilder sb = new StringBuilder("Java HandsOn");
System.out.println(sb.indexOf("HandsOn")); // Output: 5
If the string is not found then #indexOf method returns -1.
StringBuilder sb = new StringBuilder("Java HandsOn");
System.out.println(sb.indexOf("Hello")); // Output: -1
16. indexOf(String str, int fromIndex) – Returns the index of the first occurrence of the specified string, starting from the given index.
StringBuilder sb = new StringBuilder("Java HandsOn HandsOn");
System.out.println(sb.indexOf("HandsOn", 6)); // Output: 13 ( picked the second HandsOn )
If the string is not found then #indexOf method returns -1.
StringBuilder sb = new StringBuilder("Java HandsOn HandsOn");
System.out.println(sb.indexOf("Hello", 6)); // Output: -1
17. lastIndexOf(String str) – Returns the index of the last occurrence of the specified string in the StringBuilder. If the string is not found, it returns -1.
StringBuilder sb = new StringBuilder("Java HandsOn Java");
int index = sb.lastIndexOf("Java");
System.out.println("Last occurrence of 'Java': " + index); // Output : 13
StringBuilder sb = new StringBuilder("Java HandsOn Java");
int index = sb.lastIndexOf("Hello");
System.out.println("Last occurrence of 'Hello': " + index); // Output : -1
18. lastIndexOf(String str, int fromIndex) – Searches for the last occurrence of the specified string starting from the given index and moving backward.
StringBuilder sb = new StringBuilder("Java HandsOn HandsOn");
int index = sb.lastIndexOf("HandsOn", 10); // Start searching from index 10
System.out.println("Last occurrence of 'HandsOn' before index 10: " + index); // Output : 5
StringBuilder sb = new StringBuilder("Java HandsOn HandsOn");
int index = sb.lastIndexOf("Hello", 10); // Start searching from index 10
System.out.println("Last occurrence of 'HandsOn' before index 10: " + index); // Output : -1
1. Initial Capacity – When a StringBuilder object is created, it reserves memory for an initial number of characters. The default initial capacity is 16 characters if no capacity is specified. If a string is passed to the constructor, the initial capacity becomes the following:
capacity = string length + 16
StringBuilder sb1 = new StringBuilder();
System.out.println(sb1.capacity()); // Output: 16
StringBuilder sb2 = new StringBuilder("Java");
System.out.println(sb2.capacity()); // Output: 20 (4 + 16)
2. Dynamic Resizing Mechanism – When the number of characters in the StringBuilder exceeds its current capacity, Java automatically resizes the buffer using this formula:
new capacity=(old capacity×2)+2
This exponential growth strategy reduces the number of memory reallocations making StringBuilder efficient.
StringBuilder sb = new StringBuilder(5); // Initial capacity: 5
sb.append("Java HandsOn"); // Exceeds capacity
System.out.println(sb.capacity()); // Output: 12 (5 * 2 + 2)
3. ensureCapacity(int minimumCapacity) – This method pre-allocates memory to avoid frequent resizing operations, which improves performance. If minimum capacity is less than or equal to the current capacity, nothing happens but if it’s greater, the capacity increases according to the resizing formula.
StringBuilder sb = new StringBuilder();
sb.ensureCapacity(50); // Ensures at least 50 characters can be stored
System.out.println(sb.capacity()); // Output: 50
4. trimToSize() for Memory Optimization – If a StringBuilder has extra unused memory, trimToSize() reduces the capacity to match the current length. This helps free up unnecessary memory usage.
StringBuilder sb = new StringBuilder(50);
sb.append("JavaHandsOn");
System.out.println(sb.capacity()); // Output: 50
sb.trimToSize();
System.out.println(sb.capacity()); // Output: 11
Instead of increasing the capacity one character at a time (which would be slow and inefficient), StringBuilder doubles its capacity when needed. This reduces the number of times memory is allocated and copied. Consider a scenario where you append a large number of characters. Without exponential growth, Java would have to allocate new memory for every single append operation. With exponential growth, it minimizes memory copying, leading to faster execution.
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append("a");
}
StringBuilder is a powerful and efficient class in Java for handling dynamic string manipulations. Unlike String, which is immutable and creates new objects on modification, StringBuilder is mutable, allowing in-place modifications, making it significantly faster for frequent string operations.
Through this article, we explored:
For applications requiring frequent string modifications, StringBuilder is the recommended choice over String due to its efficiency, lower memory consumption, and faster execution. However, in multi-threaded environments, where thread safety is needed, StringBuffer might be a better alternative.
By understanding and leveraging StringBuilder effectively, developers can write more optimized and high-performing Java applications.
So this is all about the StringBuilder in Java. If you have any questions on this topic, please raise them in the comments section. If you liked this article then please share this post with your friends and colleagues.