Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why to use StringBuffer in Java instead of the string concatenation operator

People also ask

What is the difference between concatenation of strings using and StringBuffer?

The String class is immutable. The StringBuffer class is mutable. String is slow and consumes more memory when we concatenate too many strings because every time it creates new instance. StringBuffer is fast and consumes less memory when we concatenate t strings.

Why do we prefer StringBuffer class in place of String class?

The StringBuffer class is used to represent characters that can be modified. The significant performance difference between these two classes is that StringBuffer is faster than String when performing simple concatenations. In String manipulation code, character strings are routinely concatenated.

What is the advantage of StringBuffer in Java?

The advantage of string buffer is that it automatically grows when there is a need to add characters and substrings in between or at the bottom. String builder is one of java's mutable string objects. String builders can be modified at any point through method invocations.

Which one is better String or StringBuffer?

String is immutable whereas StringBuffer and StringBuilder are mutable classes. StringBuffer is thread-safe and synchronized whereas StringBuilder is not. That's why StringBuilder is faster than StringBuffer. String concatenation operator (+) internally uses StringBuffer or StringBuilder class.


It's better to use StringBuilder (it's an unsynchronized version; when do you build strings in parallel?) these days, in almost every case, but here's what happens:

When you use + with two strings, it compiles code like this:

String third = first + second;

To something like this:

StringBuilder builder = new StringBuilder( first );
builder.append( second );
third = builder.toString();

Therefore for just little examples, it usually doesn't make a difference. But when you're building a complex string, you've often got a lot more to deal with than this; for example, you might be using many different appending statements, or a loop like this:

for( String str : strings ) {
  out += str;
}

In this case, a new StringBuilder instance, and a new String (the new value of out - Strings are immutable) is required in each iteration. This is very wasteful. Replacing this with a single StringBuilder means you can just produce a single String and not fill up the heap with Strings you don't care about.


For simple concatenations like:

String s = "a" + "b" + "c";

It is rather pointless to use StringBuffer - as jodonnell pointed out it will be smartly translated into:

String s = new StringBuffer().append("a").append("b").append("c").toString();

BUT it is very unperformant to concatenate strings in a loop, like:

String s = "";
for (int i = 0; i < 10; i++) {
    s = s + Integer.toString(i);
}

Using string in this loop will generate 10 intermediate string objects in memory: "0", "01", "012" and so on. While writing the same using StringBuffer you simply update some internal buffer of StringBuffer and you do not create those intermediate string objects that you do not need:

StringBuffer sb = new StringBuffer();
for (int i = 0; i < 10; i++) {
    sb.append(i);
}

Actually for the example above you should use StringBuilder (introduced in Java 1.5) instead of StringBuffer - StringBuffer is little heavier as all its methods are synchronized.


One shouldn't be faster than the other. This wasn't true before Java 1.4.2, because when concatenating more than two strings using the "+" operator, intermediate String objects would be created during the process of building the final string.

However, as the JavaDoc for StringBuffer states, at least since Java 1.4.2 using the "+" operator compiles down to creating a StringBuffer and append()ing the many strings to it. So no difference, apparently.

However, be careful when using adding a string to another inside a loop! For example:

String myString = "";

for (String s : listOfStrings) {
  // Be careful! You're creating one intermediate String object
  // for every iteration on the list (this is costly!)
  myString += s;
}

Keep in mind, however, that usually concatenating a few strings with "+" is cleaner than append()ing them all.


Under the hood, it actually creates and appends to a StringBuffer, calling toString() on the result. So it actually doesn't matter which you use anymore.

So

String s = "a" + "b" + "c";

becomes

String s = new StringBuffer().append("a").append("b").append("c").toString();

That's true for a bunch of inlined appends within a single statement. If you build your string over the course of multiple statements, then you're wasting memory and a StringBuffer or StringBuilder is your better choice.


I think that given jdk1.5 (or greater) and your concatenation is thread-safe you should use StringBuilder instead of StringBuffer http://java4ever.blogspot.com/2007/03/string-vs-stringbuffer-vs-stringbuilder.html As for the gains in speed: http://www.about280.com/stringtest.html

Personally I'd code for readability, so unless you find that string concatenation makes your code considerably slower, stay with whichever method makes your code more readable.


In some cases this is obsolete due to optimisations performed by the compiler, but the general issue is that code like:

string myString="";
for(int i=0;i<x;i++)
{
    myString += "x";
}

will act as below (each step being the next loop iteration):

  1. construct a string object of length 1, and value "x"
  2. Create a new string object of size 2, copy the old string "x" into it, add "x" in position 2.
  3. Create a new string object of size 3, copy the old string "xx" into it, add "x" in position 3.
  4. ... and so on

As you can see, each iteration is having to copy one more character, resulting in us performing 1+2+3+4+5+...+N operations each loop. This is an O(n^2) operation. If however we knew in advance that we only needed N characters, we could do it in a single allocation, with copy of just N characters from the strings we were using - a mere O(n) operation.

StringBuffer/StringBuilder avoid this because they are mutable, and so do not need to keep copying the same data over and over (so long as there is space to copy into in their internal buffer). They avoid performing an allocation and copy proportional to the number of appends done by over-allocing their buffer by a proportion of its current size, giving amortized O(1) appending.

However its worth noting that often the compiler will be able to optimise code into StringBuilder style (or better - since it can perform constant folding etc.) automatically.


Java turns string1 + string2 into a StringBuffer construct, append(), and toString(). This makes sense.

However, in Java 1.4 and earlier, it would do this for each + operator in the statement separately. This meant that doing a + b + c would result in two StringBuffer constructs with two toString() calls. If you had a long string of concats, it would turn into a real mess. Doing it yourself meant you could control this and do it properly.

Java 5.0 and above seem to do it more sensibly, so it's less of a problem and is certainly less verbose.