If you are dynamically generating strings in your Java program, one of the best things you can do for your program is to build your string using a StringBuilder
or StringBuffer
, as opposed to using a regular old String
.
The reason for this? In Java, strings are immutable, and every time you concatenate a string that the program hasn’t seen before, a new string object is created and stored in the heap. This means the whole process involves a lot of reading from and writing to the memory. The StringBuilder
and StringBuffer
in Java are objects that are designed to do string concatenation in a more efficient manner, but how much more?
We’ve got a simple Java program here that you can run from your browser so you can see it for yourself.
The program
This program that we wrote dynamically builds a string from A to Z using three different classes, and times how long each takes to complete:
String
StringBuilder
StringBuffer
You can copy the program below, or run it on this online Java compiler here.
public class StringBuilderPerformanceTest { public static void main(String args[]) { System.out.println("Dynamically building a string from 'A' to 'Z' characters using a String, StringBuilder and StringBuffer..."); System.out.println(); // Measuring the time and memory for regular strings. long startTime = System.nanoTime(); String s = ""; for(char c = 'A'; c <= 'Z'; c++) { s += c; } long endTime = System.nanoTime(); System.out.printf("Regular string took %.3f milliseconds to compile.%n", (endTime - startTime) / 1000000.0); // Measuring the time and memory for StringBuilder strings. startTime = System.nanoTime(); StringBuilder sb = new StringBuilder(); for(char c = 'A'; c <= 'Z'; c++) { sb.append(c); } endTime = System.nanoTime(); System.out.printf("StringBuilder string took %.3f milliseconds to compile.%n", (endTime - startTime) / 1000000.0); // Measuring the time and memory for StringBuffer strings. startTime = System.nanoTime(); StringBuffer sbf = new StringBuffer(); for(char c = 'A'; c <= 'Z'; c++) { sbf.append(c); } endTime = System.nanoTime(); System.out.printf("StringBuffer string took %.3f milliseconds to compile.%n", (endTime - startTime) / 1000000.0); } }
Article continues after the advertisement:
Here is the output of the program from running it on JDoodle (note that you will yield slightly different results every run):
Dynamically building a string from 'A' to 'Z' characters using a String, StringBuilder and StringBuffer... Regular string took 24.256 milliseconds to compile. StringBuilder string took 0.047 milliseconds to compile. StringBuffer string took 0.138 milliseconds to compile.
In other words…
- The
StringBuilder
algorithm finished its task about 500 times faster than theString
algorithm. - The
StringBuilder
is about 3 times faster than theStringBuffer
.
Again, note that you may get slightly different results when you run the code yourself! But the StringBuilder
and StringBuffer
should always be miles faster than using String
objects!
Difference between StringBuilder
and StringBuffer
You will always want to use the StringBuilder
over the StringBuffer
in almost all instances, unless you are:
- Running a multi-thread program, and;
- Are building the string using multiple threads
This is because the StringBuffer
is thread-safe. What this means is that StringBuffer
objects can avoid race conditions — i.e. it will not allow 2 threads to update the StringBuffer
at the same time.
Article continues after the advertisement: