String vs StringBuffer vs StringBuilder in Java

Difference between String, StringBuffer, and StringBuilder

No matter which kind of application you are working you will find the heavy usage of Java String class but if you do profiling of your application you will find that String is the one class which creates lots of garbage because of much temporary String created in the program.

In this Java tutorial we will see What is String in Java, some important properties of String in Java, What is StringBuffer in Java , When to use StringBuffer in Java , StringBuilder in Java and how it can be used in place of StringBuffer,  What are differences between String and StringBuffer and StringBuilder in Java  which is also a frequently asked core Java question and mostly String vs StringBuilder vs StringBuffer.

Now let's start with String.

Differences between String, StringBuffer, and StringBuilder in Java

String in Java

string and stringbuffer, string vs stringbuffer vs stringbuilderBefore looking difference between String and StringBuffer or StringBuilder let’s see some fundamental properties of String Class in Java

1) The string is immutable in Java:  String is by design immutable in Java you can check this post for a reason. Immutability offers a lot of benefit to the String class e.g. his hashcode value can be cached which makes it a faster hashmap key and one of the reasons why String is a popular key in HashMap. Because String is final it can be safely shared between multiple threads  without any extra synchronization.

2) When we represent a string in double quotes like "abcd" they are referred as String literal and String literals are created in String pools. When you compare two String literals using equality operator "==" it returns true because they are the actually same instance of String. Anyway comparing an object with equality operator is bad practice in Java and you should always use the equals method to check equality.

3) The "+" operator is overloaded for String and used to concatenated two string. Internally "+" operation is implemented using either StringBuffer or StringBuilder. See Core Java for Impatient for more details on String concatenation in Java.

4) Strings are backed up by character Array and represented in UTF-16 format. By the way, this behavior can cause a memory leak in String because same character array is shared between source String and SubString which can prevent source String from being garbage collected. See How SubString works in Java for more details.

5) String class overrides equals() and hashcode() method and two Strings are considered to be equal if they contain exactly same character in same order and in same case. If you want to ignore case comparison of two strings consider using equalsIgnoreCase() method. See  how to correctly override equals method in Java  to learn more about best practices on equals method. Another worth noting point is that equals method must be consistent with compareTo() method for String because SortedSet and SortedMap e.g. TreeMap use the compareTo method to compare String in Java.

7) toString() method provides String representation of any object and it's declared in Object class and it's recommended for other class to implement this and provide String representation.

8) The string is represented using the UTF-16 format in Java.

9) In Java, you can create String from char array, byte array, another string, from StringBuffer or from StringBuilder. Java String class provides a constructor for all of these.

10) Even though all StringBuffer, StringBuilder, and String are from same type hierarchy i.e. they extend from CharSequence interface, you cannot cast StringBuilder to StirngBuffer or StringBuilder to String in Java. It will throw java.lang.ClasscastException, if you tried to cast even StringBuffer to String in Java.

Here is a nice diagram which shows the relationship between StringBuffer, StringBuilder, and String in Java:

Difference between StringBuffer and String in Java

Problem with String in Java

One of its biggest strength Immutability is also biggest problem of Java String if not used correctly. Many times we create a String and then perform a lot of operation on them e.g. converting a string into uppercase, lowercase , getting substring out of it , concatenating with other string etc. Since String is an immutable class every time a new String is created and the older one is discarded which creates lots of temporary garbage in the heap.

If String is created using String literal they remain in the String pool. To resolve this problem Java provides us, two Classes, StringBuffer and StringBuilder. String Buffer is an older class but StringBuilder is relatively new and added in JDK 5.

Differences between String and StringBuffer in Java

The main difference between String and StringBuffer is String is immutable while StringBuffer is mutable means you can modify a StringBuffer object once you created it without creating any new object. This mutable property makes StringBuffer an ideal choice for dealing with Strings in Java.

You can convert a StringBuffer into String by its toString() method. String vs StringBuffer or what is the difference between StringBuffer and String is one of the popular Java interview questions for either phone interview or first round. Nowadays they also include StringBuilder and ask String vs StringBuffer vs StringBuilder.

So be preparing for that. In the next section, we will see the difference between StringBuffer and StringBuilder in Java. If you are preparing for Java interviews, then you can also check Java Programming Interview exposed for more such questions, one of the best book, which covers all important topics for Java interviews.

Difference between StringBuilder and StringBuffer in Java

StringBuffer is very good with mutable String but it has one disadvantage all its public methods are synchronized which makes it thread-safe but same time slow. In JDK 5 they provided a similar class called StringBuilder in Java which is a copy of StringBuffer but without synchronization. Try to use StringBuilder whenever possible it performs better in most of the cases than StringBuffer class.

You can also use "+" for concatenating two string because "+" operation is internally implemented using either StringBuffer or StringBuilder in Java. If you see StringBuilder vs StringBuffer you will find that they are exactly similar and all API methods applicable to StringBuffer are also applicable to StringBuilder in Java.

On the other hand, String vs StringBuffer is completely different and there API is also completely different, same is true for StringBuilder vs String. Here is a nice summary of the difference between StringBuffer and StringBuilder in Java:

Difference between StringBuffer and StringBuider in Java


In summary here is list of difference between StringBuffer, String, and StringBuilder in Java :

1) The String object is immutable in Java but StringBuffer and StringBuilder are mutable objects.

2) StringBuffer is synchronized while StringBuilder is not which makes StringBuilder faster than StringBuffer.

3) Concatenation operator "+" is internally implemented using either StringBuffer or StringBuilder.

4) Use String if you require immutability, use StringBuffer in java if you need mutable + thread-safety and use StringBuilder in Java if you require mutable + without thread-safety.

That's all on famous String vs StringBuffer or StringBuffer vs StringBuilder discussion. All these differences help to avoid the common coding mistake of using String in place of StringBuffer in many places. from Java 5 onwards either use + operator of StringBuilder for concatenating String in Java. 

Other Java String tutorials from Javarevisited Blog


Anonymous said...

This same question "String vs StringBuffer" was asked on an interview. both String and StringBuffer looks similar to me before that :)

Anonymous said...

Another similirarity between StringBuffer, String and StringBuilder is they all are final class. you can not extend either String, StringBuffer or StringBuilder
you should have also mentioned about the append() and insert() method of StringBuffer and StringBuilder. append() method add character at the end of String while
insert adds character or String at a given index. anyway On difference between StringBuffer and StringBuilder you have only mentioned about synchronization isn't
any other difference between Stringbuilder and StringBuffer ?

Anonymous said...

Another difference between String and StringBuffer is String is immutable while StringBuffer is mutable though both classes are final.

Anonymous said...

In point 4 you say that String is backed by a UTF-8 Character Array but in point 8 you say it's represented in UTF-16 !
Which one is correct ?

Javin @ volatile keyword in java said...

Hi Anonymous, good catch, A String object represents a string in the UTF-16 format in which supplementary characters are represented by surrogate pairs. so in essence point 4 and 8 is same.

Jenny said...

If + is implemented through StringBuilder or StringBuffer internally, is it as performance draining, when we use a lot "+"s when doing System.out.println()?

Javin @ String split Java said...

Thanks for your comment Sandeep. Indeed Stringbuffer and StringBuilder are same with only difference in synchronization part.

Anonymous said...

That'll help optimize my android game (garbage collector is a bitch :p )

great explanation, thank you!

Javin @ sort array in java said...

@Anonymous, thanks for your comment and glad to hear that you like this article. you may like my other post on String e.g. How SubString works in Java and How to convert String to Date in Java

Anonymous said...

So, I would like to point out a slight flaw in the article:

You said:
"You can also use "+" for concatenating two string because "+" operation is internal implemented using either StringBuffer or StringBuilder in Java."

So, you are saying there is a scenario where I have two String Objects, lets call them S1 and S2. And I want to combine them to get another String Object. And you are saying that when I say S1 = S1 + S2, behind the scenes it is actually creating a StringBuilder object in memory, and using said StringBuilder to concatenate the strings.

Well, that's great and all, but you still end up with the same amount of garbage memory addresses when you're done.

You have 2 String Objects in memory. Then another Object is created implicitly, the StringBuilder. So we have 3 objects in memory now.

Then it will use the StringBuilder to append S1 and S2 together. This result is stored in the StringBuilders memory address. But, since the StringBuilder object was created implicitly by Java, it isn't going to return our result back to us in the form of a StringBuilder. We assigned the concatenation to a String Object, so that's what it's gunna give us.

So finally the StringBuilder can return the result back into S1, after it performs its native .toString() method on its results (Which, honestly, may even create another implicit String Object in memory, but i'm not sure about that one). Leaving us with the exact result we wanted.

But in the meantime, we created 2 garbage memory addresses. The memory that S2 was taking up is now garbage, and the memory that the implicitly created StringBuilder Object was taking up is now garbage as well.

Granted we can still access S2's memory address, because that is our String Object we created. But the implicit StringBuilder will remain garbage in memory until Garbage Collection is run.

That is exactly why they call the String immutable. A new Object in memory absolutely has to be created when making any modifications to the String Object. So simply using the "+" operation, will always leave you with some garbage memory.

So in very small/short scenarios this doesn't matter at all, because the garbage memory is a very small amount.

But when you are concatenating many Objects together, you should never ever use the "+" regardless of what its really doing behind the scenes.

If you simply created your own StringBuilder Object from the start, and used its native .append() method, then no other Objects will ever need to be created in memory. Leaving you with a 0% chance of creating garbage memory addresses.

The best way to do it looks like:

StringBuilder sb = new StringBuiler();

Javin @ arraylist sort ascending order java said...

@Anonymous, Thanks for your comment. first of all using "+" for concatenating String is not great in terms of performance as you have pointed out. at that line I was suggesting that internally + is implemented using StringBuilder but it doesn't mean that you should use + for excessive String manipulation,that's most simplest way and should be used for simple reason. having a separate StringBuilder object allows you to reuse the same object and preferred way of manipulating strings. Though I see point to correct the sentence a bit.

Anonymous said...

Quick, useful synapsis. And correct on interview questions along with what are some immutable classes... Good point made about peformance differences between "+" and .append().

Javin @ LinkedList vs ArrayList Java said...

@Anonymous, Good to know that you like Difference between StringBuffer vs String and StringBuilder in Java. I would like to thanks people who has shared there knowledge via comment as well. Look forward to see you again.

Anonymous said...

Sorry U Post things know by all already can you Explain in depth

Anonymous said...

Anonymous said...

This is nice article. Thank you so much... I knew how to String, StringBuffer and StringBuider work. :d

Vinay Dwivedi said...

why we can not use == operator to compare String and StringBuffer object while we can use equal() method to compare String and StringBuffer object?

Anonymous said...

Vinay, == operator compares the address when comparing objects and value when comparing primitive data types

Milind Paradkar said...

To prove/understand clearly that String is immutable (and creates saperate objects in memory) and StringBuffer/StringBuilder are not you can observe this- Every manipulation method in string like concate, replace returns you new Sring and original string objects remain unchanged, while same kind of methods in buffer and builder are void and actual object gets changed after these methods.

Javin @ Java String Tutorial for Beginners said...

@Milind, That's a good point. Also if you have noticed that, while applying trim(), toUpperCase() or toLowerCase() method on String, you better store the result of this operation, failing to do so will result in subtle bugs e.g.

String a = "abc";
System.out.println(a); // will still print "abc"

Correct way of doing this is
a = a.toUpperCase();

Anonymous said...

once i was asked in an interview we can made stringbuffer behave like string...i.e make string buffer immutable...

Nidhi said...

Hi, How we can make stringbuffer behave like string?

Abhinav Chawan said...

What happens in heap if we called toString() on StringBuffer or StringBuilder's object ?

This question is asked to me in an Interview.
can any one help me to understand what exactly will happen in heap.

Peter Lawrey said...

It's worth noting that StringBuffer was replaced by StringBuilder ten years ago. There is almost never a good reason to use StringBuffer as it is only thread safe for single operations. If you consider that using StringBuffer for not more than one operation is pretty useless, you can see why StringBuffer was rather pointless.

A.M.S Sumanasooriya said...

Is there any possibility to loose the tail of a HUGE stringBuilder if toString() method is called on it get string?

Anonymous said...

So i was interviewing candidates for my company in McLean-VA and asked this and too bad none of the candidates know the answers my question-
String a = "A";
String b = "B";
String c = "C";

Question: String d = a + a + b + c;
All in all in the above question how many objects have you created? I leave to the candidates to answer again..

Javin Paul said...

@Anonymous, interesting question. My answer is 5, let me know if there is a trick :-). The 3 String objects are right there, then one StringBuffer or StringBuilder depending upon which Java version you are using for concatenation and finally one more String which will be stored in d, and returned as StringBuffer.toString() method.

Houssem said...

Use String if you need Immutable and thread safe. As any Immutable object is a thread safe. So as a conclusion you want a thread safe class use String (Immutable) or StrinhBuffee (muttable). You want a non thread safe for a faster manipulation use the StringBuilder (Immutable of course).

Post a Comment