Why to use StringBuffer in Java instead of the str

2019-01-04 23:12发布

Someone told me it's more efficient to use StringBuffer to concatenate strings in Java than to use the + operator for Strings. What happens under the hood when you do that? What does StringBuffer do differently?

18条回答
太酷不给撩
2楼-- · 2019-01-04 23:51

As said, the String object is ummutable, meaning once it is created (see below) it cannot be changed.

String x = new String("something"); // or

String x = "something";

So when you attempt to concanate String objects, the value of those objects are taken and put into a new String object.

If you instead use the StringBuffer, which IS mutable, you continually add the values to an internal list of char (primitives), which can be extended or truncated to fit the value needed. No new objects are created, only new char's are created/removed when needed to hold the values.

查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-01-04 23:52

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.

查看更多
beautiful°
4楼-- · 2019-01-04 23:54

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.

查看更多
太酷不给撩
5楼-- · 2019-01-04 23:54

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.

查看更多
相关推荐>>
6楼-- · 2019-01-04 23:54

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.

查看更多
乱世女痞
7楼-- · 2019-01-04 23:57

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.

查看更多
登录 后发表回答