2

Possible Duplicate:
StringBuilder vs String concatenation in toString() in Java

Why are StringBuilders better to use than normal String Concatenation?

Community
  • 1
  • 1
Jamal Khan
  • 9,371
  • 6
  • 23
  • 23
  • They are not always better. In fact, I *very rarely* ever use a StringBuilder -- the exception being places where StringBuilder is well suited, such as, say, Template processing ;-) –  Nov 02 '11 at 02:24

7 Answers7

7

The java compiler these days is smart enough that it will use StringBuilder to concatenate strings anyway.

This makes the following code identical

System.out.println("test = "+test+" test2 = "+test2);
System.out.println((new StringBuilder()).append("test =  ").append(test).append("test2 = ").append(test2).toString());

So if your strings fall on a single executable line, you should never be afraid of using string concatanation.

However if you're looping through an array of something and concatenating the strings together the java runtime will be creating all these new StringBuilder then concatenating them together, so it's more efficient in this case to supply your own single instance of StringBuilder

StringBuilder sb = new StringBuilder();
for(String test : testStrings) {
   sb.append(" ").appendtest);   
}
linead
  • 1,636
  • 14
  • 25
  • 3
    "... these days ..." ? This optimization has been in Java compilers for a very long time. It is even mentioned in the JLS First Edition; see http://java.sun.com/docs/books/jls/first_edition/html/15.doc.html#40226 ... albeit that it talks about using "StringBuffer or a similar technique". – Stephen C Nov 02 '11 at 03:09
  • 1
    right StringBuilder has only been around since 1.5 though. Given that this optimisation has been around for so long I wonder why so many people still don't know about it. – linead Nov 02 '11 at 03:19
  • 1
    I don't have any evidence for this, but I suspect that the "or similar technique" was a reference to some magic in the (then) native implementation of String. StringBuffer uses mutex locking which was (in the early days) rather expensive. – Stephen C Nov 02 '11 at 03:25
2

Because Strings are immutable. When you do a string concatenation, you create many strings as temporaries that must then be garbage collected. With StringBuilder, there's an underlying mutable data structure, so you just keep using that.

The effect is to both limit the amount of GC and reduce the number of JVM instructions that are executed. Instructions aren't usually a big issue, but I've seen bad uses of string concatenation push a JVM into massive GC loads.

Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
1

StringBuilder is mutable so you are not creating new string.

Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142
  • While true this is not justification for why it's "better" -- this mutation effect *could* be viewed as "not better", depending upon task. –  Nov 02 '11 at 02:25
  • 1
    @pst, ofcourse! Strings were made mutable for a reason! However, generally speaking in terms of concatenations, and yes if you have a small number of them, you probably don't mind anyways, but if you are dealing with a good number of them, buffers are definitely better. Basically, I am saying that its better to avoid creating unnecessary short lived objects if there's a easy way out (as is in this case). – aishwarya Nov 02 '11 at 02:35
  • @aishwarya - it is not *necessarily* true the StringBuilders are better. See linead's answer – Stephen C Nov 02 '11 at 03:14
1

StringBuilder does not create new Strings in the pool on operations such as concatenation, substring e.t.c. In short, every time u make an operation on String, a new String is created in the pool.

String x = "abc"
x= x+"def";

so three strings have been created in the pool. "abc", "def". "abcdef".....where as same task would have been achieved by StringBUilder while using only one object.

StringBuilder is recommended over StringBuffer, because StringBuffer is thread safe and have synchronized methods, so until or unless thread safe is required, stringbuilder is recommended as string buffer might cause performance overhead, although negligible.

Zohaib
  • 7,026
  • 3
  • 26
  • 35
1

I decided to put your question to the 'profiler' test by running 3 simple test cases through the YourKit Java Profiler. I performed three tests using String, StringBuilder and StringBuffer.

The source for each is as follows:

 public void testString() throws Exception {

    for ( int x = 0; x < 10000000; x++ ) {
        String s = "the quick brown fox jumped over the lazy dogs. ";
        for ( int i = 0 ; i < 5; i++ ) {
            s += s;
        }
    }
}
public void testStringBuilder() throws Exception {

    for ( int x = 0; x < 10000000; x++ ) {
        StringBuilder s = new StringBuilder("the quick brown fox jumped over the lazy dogs. ");
        for ( int i = 0 ; i < 5; i++ ) {
            s.append(s);
        }
    }
}

public void testStringBuffer() throws Exception {

    for ( int x = 0; x < 10000000; x++ ) {
        StringBuffer s = new StringBuffer("the quick brown fox jumped over the lazy dogs. ");
        for ( int i = 0 ; i < 5; i++ ) {
            s.append(s);
        }
    }
}

Each of these test cases was executed with 'Tracing' enabled on a 64-bit JDK1.6_27. Below are the timing results from each test (sorry, had to remove images due to SO limits, posting CSV output instead).

The first thing you'll notice is that in both the String an StringBuffer test, the JVM is using StrinbBuffers as the internal implementation. However, in the String case, the overall performance is much worse. The key to the difference is in the invocation count.

In the String case, use of the concatenation operator ("+=") results in the creation of two StringBuffer instances (see the "Invocation Count" results: 99M vs 48M).

So if you're going to do lots of concatenation, use a StringBuffer directly.

String:

"Name","Time (ms)","Avg. Time (ms)","Own Time (ms)","Invocation Count","Level"
"com.altosresearch.utils.test.StringsTest.testString()","190497","190497","0","1", "7"
"java.lang.StringBuilder.append(String)","117742","0","117742","99825142", "8"
"java.lang.StringBuilder.toString()","46142","0","46142","49912563", "8"
"java.lang.StringBuilder.<init>()","26612","0","26612","49912563", "8"

StringBuilder:

"Name","Time (ms)","Avg. Time (ms)","Own Time (ms)","Invocation Count","Level"
"com.altosresearch.utils.test.StringsTest.testStringBuilder()","90179","90179","0","1", "7"
"java.lang.StringBuilder.append(CharSequence)","79212","0","79212","48924577", "8"
"java.lang.StringBuilder.<init>(String)","10966","0","10966","9784916", "8"

StringBuffer:

"Name","Time (ms)","Avg. Time (ms)","Own Time (ms)","Invocation Count","Level"
"com.altosresearch.utils.test.StringsTest.testStringBuffer()","83518","83518","0","1", "7"
"java.lang.StringBuffer.append(StringBuffer)","73207","0","73207","48694049", "8"
"java.lang.StringBuffer.<init>(String)","10311","0","10311","9738810", "8"
Jason Buberel
  • 4,930
  • 2
  • 19
  • 10
0

Since strings are immutable, you may want to use the StringBuilder class if you're going to alter the String in the code.

thatbennyguy
  • 298
  • 5
  • 16
0

String is immutable so every concat creates a new object, Stringbuffer/builder are mutable. A note is offered at this link

aishwarya
  • 1,970
  • 1
  • 14
  • 22