StringBuilder vs StringBuffer in Java

1. Overview

In this short article, we’re going to look at similarities and differences between StringBuilder and StringBuffer in Java.

Simply put, StringBuilder was introduced in Java 1.5 as a replacement for StringBuffer.

2. Similarities

Both StringBuilder and StringBuffer create objects that hold a mutable sequence of characters. Let’s see how this works, and how it compares to an immutable String class:

String immutable = "abc";
immutable = immutable + "def";

Even though it may look like that we’re modifying the same object by appending “def”, we are creating a new one because String instances can’t be modified.

When using either StringBuffer or StringBuilder, we can use the append() method:

StringBuffer sb = new StringBuffer("abc");
sb.append("def");

In this case, there was no new object created. We have called the append() method on sb instance and modified its content. StringBuffer and StringBuilder are mutable objects.

3. Differences

StringBuffer is synchronized and therefore thread-safe. StringBuilder is compatible with StringBuffer API but with no guarantee of synchronization.

Because it’s not a thread-safe implementation, it is faster and it is recommended to use it in places where there’s no need for thread safety.

3.1. Performance

In small iterations, the performance difference is insignificant. Let’s do a quick micro-benchmark with JMH:

@State(Scope.Benchmark)
public static class MyState {
    int iterations = 1000;
    String initial = "abc";
    String suffix = "def";
}

@Benchmark
public StringBuffer benchmarkStringBuffer(MyState state) {
    StringBuffer stringBuffer = new StringBuffer(state.initial);
    for (int i = 0; i < state.iterations; i++) {
        stringBuffer.append(state.suffix);
    }
    return stringBuffer;
}

@Benchmark
public StringBuilder benchmarkStringBuilder(MyState state) {
    StringBuilder stringBuilder = new StringBuilder(state.initial);
    for (int i = 0; i < state.iterations; i++) {
        stringBuilder.append(state.suffix);
    }
    return stringBuilder;
}

We have used the default Throughput mode – i.e. operations per unit of time (higher score is better), which gives:

Benchmark                                          Mode  Cnt      Score      Error  Units
StringBufferStringBuilder.benchmarkStringBuffer   thrpt  200  86169.834 ±  972.477  ops/s
StringBufferStringBuilder.benchmarkStringBuilder  thrpt  200  91076.952 ± 2818.028  ops/s

If we increase the number of iterations from 1k to 1m then we get:

Benchmark                                          Mode  Cnt   Score   Error  Units
StringBufferStringBuilder.benchmarkStringBuffer   thrpt  200  77.178 ± 0.898  ops/s
StringBufferStringBuilder.benchmarkStringBuilder  thrpt  200  85.769 ± 1.966  ops/s

However, let’s bear in mind that this is a micro-benchmark, which may or may not have a real impact on the actual, real-world performance of an application.

4. Conclusions

Simply put, the StringBuffer is a thread-safe implementation and therefore slower than the StringBuilder.

In single-threaded programs, we can take of the StringBuilder. Yet, the performance gain of StringBuilder over StringBuffer may be too small to justify replacing it everywhere. It’s always a good idea to profile the application and understand its runtime performance characteristics before doing any kind of work to replace one implementation with another.

Finally, as always, the code used during the discussion can be found over on GitHub.

Related posts:

Java Program to Implement WeakHashMap API
Java Program to Check for balanced parenthesis by using Stacks
Anonymous Classes in Java
Java Program to Generate a Graph for a Given Fixed Degree Sequence
Java – Create a File
Filtering a Stream of Optionals in Java
Java Program to Generate All Subsets of a Given Set in the Gray Code Order
Java Program to Implement Depth-limited Search
Stack Memory and Heap Space in Java
Java Program to Represent Graph Using Incidence Matrix
Java Program to Implement Red Black Tree
Jackson Annotation Examples
Java Program to Implement Sieve Of Eratosthenes
Guide to Java OutputStream
Hướng dẫn Java Design Pattern – State
Java equals() and hashCode() Contracts
Java Program to Check Whether an Undirected Graph Contains a Eulerian Path
Java Program to Implement Graham Scan Algorithm to Find the Convex Hull
Java Program to Implement vector
Java Program to Implement Uniform-Cost Search
Java Program to Implement Affine Cipher
Java Program to Check if a Given Graph Contain Hamiltonian Cycle or Not
Java Program to Implement Heap Sort Using Library Functions
Hướng dẫn tạo và sử dụng ThreadPool trong Java
Java Program to Implement Stack using Two Queues
Java Program to Implement Nth Root Algorithm
Spring Boot Tutorial – Bootstrap a Simple Application
Copy a List to Another List in Java
Java Program to Generate All Possible Combinations of a Given List of Numbers
Guide to Java 8’s Collectors
Java Program to Generate All Pairs of Subsets Whose Union Make the Set
Spring Boot - Application Properties