StringBuilder
When creating large strings in Java, concatenation ("+") becomes slow—this operation requires a lot of copying. StringBuilder
can alleviate this problem.
StringBuilder
speeds up concatenation by using a shared buffer. The buffer is mutable, so no copying is needed for appends.
Here we import java.lang.StringBuilder
. We use StringBuilder
in a for
-loop. StringBuilder
optimizes cases where many append()
calls occur.
StringBuilder
. Then we use a for
-loop and append 6 values (2 in each iteration) to the StringBuilder
.String
object. We display the resulting String
to the Console
with the System.out.println
method.import java.lang.StringBuilder; public class Program { public static void main(String[] args) { // Part 1: create a new StringBuilder. var builder = new StringBuilder(); // ... Loop and append values. for (int i = 0; i < 3; i++) { builder.append(i).append(" "); } // Part 2: convert to string. var result = builder.toString(); // ... Print result. System.out.println(result); } }0 1 2
The StringBuilder
can append many types of data. We are not restricted to strings. With the append()
method, we can add ints, doubles, chars—any numeric type.
append()
on the result of a previous append()
call. Append
returns the original StringBuilder
.String
instance from the StringBuilder
with toString()
, and write the String
to the screen.import java.lang.StringBuilder; public class Program { public static void main(String[] args) { int value1 = 300; double value2 = 3.14; short value3 = 5; char value4 = 'A'; // Part 1: create StringBuilder and add 4 values to it. StringBuilder builder = new StringBuilder(); builder.append(value1).append("\n"); builder.append(value2).append("\n"); builder.append(value3).append("\n"); builder.append(value4); // Part 2: display results. String result = builder.toString(); System.out.println(result); } }300 3.14 5 A
Insert
A StringBuilder
has a mutable buffer. So we can quickly append, or insert, data. Here we use the insert method. It receives 2 arguments: an index, and a value we want to insert.
string
(or other value) as the second argument. This is the data that is placed into the StringBuilder
.import java.lang.StringBuilder; public class Program { public static void main(String[] args) { // Initialize StringBuilder with this value. StringBuilder builder = new StringBuilder("ABC"); // Insert this substring at position 2. builder.insert(2, "xyz"); System.out.println(builder); } }ABxyzC
IndexOf
A StringBuilder
can be searched. We use the indexOf
method to search for a substring within the StringBuilder
's data. This method searches forward.
StringBuilder
, the first index where it occurs is returned as an int
.indexOf
.import java.lang.StringBuilder; public class Program { public static void main(String[] args) { StringBuilder builder = new StringBuilder("abc"); // Try to find this substring. int result = builder.indexOf("bc"); System.out.println(result); // This substring does not exist. int result2 = builder.indexOf("de"); System.out.println(result2); } }1 -1
Delete
This removes a range of characters. We pass it 2 int
arguments. The first argument is the start index where removal is to begin. And the second argument is the end index.
import java.lang.StringBuilder; public class Program { public static void main(String[] args) { StringBuilder builder = new StringBuilder("carrot"); // Delete characters from index 2 to index 5. builder.delete(2, 5); System.out.println(builder); } }cat
Replace
This method accepts 2 indexes and replaces the characters in that range with a specified String
. Replace
on StringBuilder
works differently than replace()
on Strings.
import java.lang.StringBuilder; public class Program { public static void main(String[] args) { // Create new StringBuilder. StringBuilder b = new StringBuilder("ABC"); // Replace second character with "xyz". b.replace(1, 2, "xyz"); System.out.println(b); } }AxyzC
StringBuilders
We can append one StringBuilder
to another. We simply call append()
and pass the second StringBuilder
as an argument. The 2 StringBuilders
are combined.
public class Program { public static void main(String[] args) { StringBuilder builder = new StringBuilder("cat"); StringBuilder builder2 = new StringBuilder("dog"); // Combine 2 StringBuilders. builder.append(builder2); System.out.println(builder); } }catdog
Substring
This method is found on the AbstractStringBuilder
class
. It provides the useful ability to extract a range of characters into a new string
.
import java.lang.StringBuilder; public class Program { public static void main(String[] args) { StringBuilder builder = new StringBuilder(); builder.append("FOREST"); // Get substring after the first 2 characters. String omitFirstTwo = builder.substring(2); System.out.println(omitFirstTwo); // Get only the first 2 characters in a substring. String firstTwo = builder.substring(0, 2); System.out.println(firstTwo); } }REST FO
A for
-loop can iterate over the characters in a StringBuilder
. We access the length()
method to get the StringBuilder
's size and then use charAt()
to access chars.
length()
method returns the count of characters in the StringBuilder
. The highest index is the count of chars minus one.import java.lang.StringBuilder; public class Program { public static void main(String[] args) { StringBuilder builder = new StringBuilder("magic"); // Loop over the characters in this StringBuilder. for (int i = 0; i < builder.length(); i++) { System.out.println(builder.charAt(i)); } } }m a g i c
SetLength
We can modify the length of a StringBuilder
with setLength
. This often is useful when we want to shorten or reduce the number of characters in the object.
import java.lang.StringBuilder; public class Program { public static void main(String[] args) { StringBuilder builder = new StringBuilder("carrot"); // Use setLength to remove characters from the end. builder.setLength(3); System.out.println(builder); } }car
Capacity
The StringBuilder
in Java manages its capacity as we add elements. The capacity will increase (double
) the contents come close to filling it.
StringBuilder
. It uses for
-loop to add 20 strings of 5 characters each to the StringBuilder
.import java.lang.StringBuilder; public class Program { public static void main(String[] args) { StringBuilder builder = new StringBuilder(""); for (int i = 0; i < 20; i++) { // Print length and capacity. System.out.println("Length = " + builder.length() + "; Capacity = " + builder.capacity()); // Add 5 chars to StringBuilder. builder.append("aaaaa"); } } }Length = 0; Capacity = 16 Length = 5; Capacity = 16 Length = 10; Capacity = 16 Length = 15; Capacity = 16 Length = 20; Capacity = 34 Length = 25; Capacity = 34 Length = 30; Capacity = 34 Length = 35; Capacity = 70 Length = 40; Capacity = 70 Length = 45; Capacity = 70 Length = 50; Capacity = 70 Length = 55; Capacity = 70 Length = 60; Capacity = 70 Length = 65; Capacity = 70 Length = 70; Capacity = 70 Length = 75; Capacity = 142 Length = 80; Capacity = 142 Length = 85; Capacity = 142 Length = 90; Capacity = 142 Length = 95; Capacity = 142
Reverse
This example reverses a StringBuilder
. It calls the reverse()
method. This is an easy to reverse a string
—we first must place its contents in a StringBuilder
.
import java.lang.StringBuilder; public class Program { public static void main(String[] args) { // A StringBuilder can be reversed. StringBuilder builder = new StringBuilder(); builder.append("abc"); builder.reverse(); System.out.println(builder); } }cba
Append
performanceA StringBuilder
is massively faster in repeated appends than a String
. Append
performance is the most important thing to know about StringBuilder
.
string
. We use the string
concatenation operator.StringBuilder
. The StringBuilder
does not have a capacity set.String
adds require significant time (251 ms) while the StringBuilder
appends require less than 1 ms.import java.lang.StringBuilder; public class Program { public static void main(String[] args) { long t1 = System.currentTimeMillis(); // Version 1: add to string. String value = ""; for (int i = 0; i < 10000; i++) { value += Integer.toString(i) + ' '; } long t2 = System.currentTimeMillis(); // Version 2: append to StringBuilder. StringBuilder builder = new StringBuilder(); for (int i = 0; i < 10000; i++) { builder.append(i).append(' '); } long t3 = System.currentTimeMillis(); // ... Lengths are equal. System.out.println(value.length()); System.out.println(builder.length()); // ... Times. System.out.println(t2 - t1); System.out.println(t3 - t2); } }48890 48890 251 ms, String + operator (20000 adds) 0 ms, StringBuilder append (20000 calls)
Capacity
performanceHere we revisit capacity. How much does setting a capacity help if we know we will be adding as many as 1 million characters to our StringBuilder
?
StringBuilder
grows to a size of one million chars with no capacity set.StringBuilder
meanwhile uses an exact capacity of 1,000,000. The two are benchmarked.StringBuilder
nearly twice as fast to complete its meaningless task.import java.lang.StringBuilder; public class Program { public static void main(String[] args) { long t1 = System.currentTimeMillis(); // Version 1: does not use capacity. StringBuilder builder = new StringBuilder(); for (int i = 0; i < 1000000; i++) { builder.append(' '); } long t2 = System.currentTimeMillis(); // Version 2: uses exact capacity. StringBuilder builder2 = new StringBuilder(1000000); for (int i = 0; i < 1000000; i++) { builder2.append(' '); } long t3 = System.currentTimeMillis(); // ... Times. System.out.println(t2 - t1); System.out.println(t3 - t2); } }10 ms, no capacity 6 ms, exact capacity
Append
String
versus char
Here is another benchmark. It compares calling append()
with a one-character String
literal versus a char
. The String
argument is slower.
String
literal in a tight loop, repeated many times.string
, but instead append a single character—a character literal.char
argument to append()
than a String
argument. I have found this helps many programs.import java.lang.StringBuilder; public class Program { public static void main(String[] args) { long t1 = System.currentTimeMillis(); // Version 1: appends one-char strings. StringBuilder builder = new StringBuilder(); for (int i = 0; i < 1000000; i++) { builder.append("X"); } long t2 = System.currentTimeMillis(); // Version 2: appends chars directly. StringBuilder builder2 = new StringBuilder(); for (int i = 0; i < 1000000; i++) { builder2.append('X'); } long t3 = System.currentTimeMillis(); // ... Times. System.out.println(t2 - t1); System.out.println(t3 - t2); } }15 ms, append() String argument 7 ms, append() char argument
ContentEquals
With this method we can compare a String
to a StringBuilder
. The character data is compared. We call contentEquals
on a String
instance.
StringBuilder
helps in many program parts. But often its best uses are in loops—many iterations occur, and many append calls are invoked.