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.
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.
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.
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
- String
s 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 String
s 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):
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With