92

I just encountered StringBuilder for the first time and was surprised since Java already has a very powerful String class that allows appending.

Why a second String class?

Where can I learn more about StringBuilder?

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
an00b
  • 11,338
  • 13
  • 64
  • 101
  • 1
    See also: [*Exact difference between CharSequence and String in java*](https://stackoverflow.com/q/11323962/642706) and [my nifty class diagram](https://i.stack.imgur.com/PIFk9.png). – Basil Bourque Apr 11 '18 at 20:49
  • I just wanted to note this actually came up as an interview question for me once. They asked what I would to populate a large String..... – preOtep Dec 20 '19 at 15:24
  • The `StringBuilder` is 100s of times faster than strings when appending. Here's an article with a Java script you can run to see it for yourself: https://blog.terresquall.com/2023/08/try-it-yourself-compare-performance-java-string-stringbuilder-stringbuffer/ – John Doe Aug 14 '23 at 03:28

9 Answers9

185

String does not allow appending. Each method you invoke on a String creates a new object and returns it. This is because String is immutable - it cannot change its internal state.

On the other hand StringBuilder is mutable. When you call append(..) it alters the internal char array, rather than creating a new string object.

Thus it is more efficient to have:

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

rather than str += i, which would create 500 new string objects.

Note that in the example I use a loop. As helios notes in the comments, the compiler automatically translates expressions like String d = a + b + c to something like

String d = new StringBuilder(a).append(b).append(c).toString();

Note also that there is StringBuffer in addition to StringBuilder. The difference is that the former has synchronized methods. If you use it as a local variable, use StringBuilder. If it happens that it's possible for it to be accessed by multiple threads, use StringBuffer (that's rarer)

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 28
    +1. You could add: "hence StrungBuilder looks for performance" and "Java compilers substitutes expressions like A + B + C with new StringBuilder(A).append(B).append(C).toString() in order to avoid object creation performance penalties" :) – helios Mar 08 '11 at 15:04
  • and all Thank you very much. You all deserve +1's (which will be delivered promptly :) – an00b Mar 08 '11 at 15:04
  • super like the recall of 'immutable' objects. – Gary Tsui May 30 '11 at 08:46
  • Great responses. What I miss however is the reason why we can't just have the compiler figuring out when to just use Stringbuilder *most of the time*, including in for loops, so that you don't need to think about it as a dev. :) – worldsayshi Sep 02 '15 at 08:11
  • 1
    Good answer . I would like to add these lines : String is immutable as the array (i.e char [] value) which holds string is declared final but in case of StringBuilder the array (i.e char [] value) which holds string is not final. You can make changes in the array which holds string in case of Stringbuilder – Deen John Jun 25 '16 at 09:42
  • are these methods `toLowerCase`, `toUpperCase` also create a new String? – Adiyat Mubarak Sep 16 '17 at 13:52
  • @AdiyatMubarak yes. An immutable object's state cannot be changed, so for example `toLowerCase` cannot change the current string it is being called from. So it creates a new one from the current string. – Bondolin Jan 26 '18 at 13:14
  • Great answer! Why are other answers saying there is a performance cost of using String if the compiler will replace it anyways? – Jack Mar 09 '21 at 02:35
70

Here is a concrete example on why -

int total = 50000;
String s = ""; 
for (int i = 0; i < total; i++) { s += String.valueOf(i); } 
// 4828ms

StringBuilder sb = new StringBuilder(); 
for (int i = 0; i < total; i++) { sb.append(String.valueOf(i)); } 
// 4ms

As you can see the difference in performance is significant.

Amir Raminfar
  • 33,777
  • 7
  • 93
  • 123
19

String class is immutable whereas StringBuilder is mutable.

String s = "Hello";
s = s + "World";

Above code will create two object because String is immutable

StringBuilder sb = new StringBuilder("Hello");
sb.append("World");

Above code will create only one object because StringBuilder is not immutable.

Lesson: Whenever there is a need to manipulate/update/append String many times go for StringBuilder as its efficient as compared to String.

Umesh K
  • 13,436
  • 25
  • 87
  • 129
8

StringBuilder is for, well, building strings. Specifically, building them in a very performant way. The String class is good for a lot of things, but it actually has really terrible performance when assembling a new string out of smaller string parts because each new string is a totally new, reallocated string. (It's immutable) StringBuilder keeps the same sequence in-place and modifies it (mutable).

Rex M
  • 142,167
  • 33
  • 283
  • 313
5

To be precise, StringBuilder adding all strings is O(N) while adding String's is O(N^2). Checking the source code, this is internally achieved by keeping a mutable array of chars. StringBuilder uses the array length duplication technique to achieve ammortized O(N^2) performance, at the cost of potentially doubling the required memory. You can call trimToSize at the end to solve this, but usually StringBuilder objects are only used temporarily. You can further improve performance by providing a good starting guess at the final string size.

mahogny
  • 79
  • 1
  • 2
5

The StringBuilder class is mutable and unlike String, it allows you to modify the contents of the string without needing to create more String objects, which can be a performance gain when you are heavily modifying a string. There is also a counterpart for StringBuilder called StringBuffer which is also synchronized so it is ideal for multithreaded environments.

The biggest problem with String is that any operation you do with it, will always return a new object, say:

String s1 = "something";
String s2 = "else";
String s3 = s1 + s2; // this is creating a new object.
CarlosZ
  • 8,281
  • 1
  • 21
  • 16
3

Efficiency.

Each time you concatenate strings, a new string will be created. For example:

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

This creates a new, temporary string, copies "a" and "b" into it to result in "ab". Then it creates another new, temporary string, copies "ab" and "c" into it, to result in "abc". This result is then assigned to out.

The result is a Schlemiel the Painter's algorithm of O(n²) (quadratic) time complexity.

StringBuilder, on the other hand, lets you append strings in-place, resizing the output string as necessary.

Thomas
  • 174,939
  • 50
  • 355
  • 478
  • Many JVM implementations will compile your example into a StringBuilder and then convert the end result to String. In such a case, it won't be assembled by repeated String allocations. – scottb Sep 21 '13 at 08:58
3

StringBuilder is good when you are dealing with larger strings. It helps you to improve performance.

Here is a article that I found that was helpful .

A quick google search could have helped you. Now you hired 7 different people to do a google search for you . :)

1

Java has String, StringBuffer and StringBuilder:

  • String : Its immutable

  • StringBuffer : Its Mutable and ThreadSafe

  • StringBuilder : Its Mutable but Not ThreadSafe, introduced in Java 1.5

String eg:

public class T1 {

    public static void main(String[] args){

        String s = "Hello";

        for (int i=0;i<10;i++) {

            s = s+"a";
            System.out.println(s);
        }
    }
}

}

output: 10 Different Strings will be created instead of just 1 String.

Helloa
Helloaa
Helloaaa
Helloaaaa
Helloaaaaa
Helloaaaaaa
Helloaaaaaaa
Helloaaaaaaaa 
Helloaaaaaaaaa 
Helloaaaaaaaaaa

StringBuilder eg : Only 1 StringBuilder object will be created.

public class T1 {

    public static void main(String[] args){

        StringBuilder s = new StringBuilder("Hello");

        for (int i=0;i<10;i++) {    
            s.append("a");
            System.out.println(s);
        }
    }
}
Javasick
  • 2,753
  • 1
  • 23
  • 35
Kumar Vivek Mitra
  • 33,294
  • 6
  • 48
  • 75