StringBuilder VS StringBuffer
Since String is immutable, it is very costly to use it when constructing a dynamic character string due to the fact that a new memory location will be allocated at each assignment or modification.
Since its first release, Java supports a mutable class called StringBuffer which constructs dynamic character strings through allocating just 1 memory location, this saves a lot of memory and relatively improves the performance compared with the String approach. StringBuffer was implemented as thread-safe, hence all its public methods are implicitly synchronized which leads to additional unneeded costs when using it in a single threaded environment.
Sun noticed that most of the uses of StringBuffer were with single-thread environments and developers are unnecessarily paying the cost of synchronization. So they introduced (since Java 5) a new class called StringBuilder to be a drop-in replacement for StringBuffer, the new class looks exactly similar to StringBuffer exposing the same methods with same signatures, however it’s not thread safe and not synchronized, hence more convenient and faster in single-thread environments.
1. Stringbuilder VS Stringbuffer
In the following table, we define the major similarities and differences between StringBuffer and StringBuilder:
|Both are mutable: they allocate only 1 memory location and any subsequent modifications on them are done on the same instance.||StringBuffer is implicitly synchronized hence thread safe, while StringBuilder is not thread safe and is only suitable for single threaded environments.|
|Both expose same methods with same signatures like: append, insert, replace ..etc.||StringBuilder is faster than StringBuffer since its methods are not synchronized.|
|Both are faster than String for constructing dynamic string characters.|
2. Performance test
In order to prove the performance variation between String, StringBuffer and StringBuilder when constructing a dynamic character string, we create the following test which constructs a dynamic string inside a 100000 iteration loop:
public void constructDynamicString()
long startTime = System.currentTimeMillis();
String s = "test";
//StringBuffer s = new StringBuffer("test");
//StringBuilder s = new StringBuilder("test");
for(int i=0; i<100000; i++)
s += "concat";
long endTime = System.currentTimeMillis();
System.out.println("Concat time ====== " + (endTime - startTime));
We run the above test 3 times, each approach at a time, and we get the following result:
With String, it tooks: 39068 ms
With StringBuffer, it tooks: 7ms
With StringBuilder, it tooks: 4ms
From the above results, we notice that using String object for creating a dynamic character string is way slower than using StringBuffer and StringBuilder due to the immutability fact. Additionally, StringBuilder is faster than StringBuffer since it doesn’t care about synchronization, (although it looks slightly faster, the speed would relatively differ if we increase the number of iterations).
Now, in order to decide which class to use, take into consideration the following factors:
- If you’re creating a static character string that shouldn’t be modified throughout the program flow, then use String object.
- If you’re creating a dynamic character string which needs to be shared between multiple threads, then consider using StringBuffer.
- If both factors don’t exist (which is a very common case) , then use StringBuilder.
Personally, i always prefer StringBuilder for dynamic strings, it is not common to share a dynamic string between multiple threads, however if it happens, i normally prefer to use StringBuilder with explicit synchronization rather than using StringBuffer.