String vs StringBuffer vs StringBuilder

We know that, String is one of the most frequently used class in Java programming.

Many java programmers are not aware of the fact that String is immutable in java which means every modification to a string creates a new String.

Modification could be concatenation of string with other string or converting string to lower case or trimming the string to remove spaces.

In all these scenarios, String creates a new object.

If you think of any solution in Java where any modification to string should not create new String object rather it has to modify the same string.

Solution for the same is either StringBuffer or StringBuilder


Lets see the difference between String,StringBuilder and StringBuffer


1) Object creation


String can be created in 2 ways , either using new or by string literal in double quotes where as StringBuffer and StringBuilder object has to be created using “new” only.

Example:

  1. class StringBufferBuilder1 {  
  2. public static void main(String args[]){
  3. String s1= new String("java");
  4. String s2= "simple";
  5.  
  6. StringBuffer buffer= new StringBuffer("java");
  7.  
  8. StringBuilder builder= new StringBuilder("java ");
  9.  
  10. }  
  11. }  
class StringBufferBuilder1 {  
public static void main(String args[]){ 
String s1= new String("java");
String s2= "simple";

StringBuffer buffer= new StringBuffer("java");

StringBuilder builder= new StringBuilder("java ");

}  
}  



2) Immutability


String is immutable and hence it creates new object for each modification

Whereas StringBuffer and StringBuilder are mutable which means same string will be modified for every modification of string.

Example:

  1. class StringBufferBuilder1 {  
  2. public static void main(String args[]){
  3. String s= new String("java ");
  4. s.concat("in simple way");
  5. System.out.println(s);
  6.  
  7. StringBuffer buffer= new StringBuffer("java ");
  8. buffer.append("in simple way");
  9. System.out.println(buffer);
  10.  
  11. StringBuilder builder= new StringBuilder("java ");
  12. builder.append("in simple way");
  13. System.out.println(builder);
  14. }  
  15. }  
class StringBufferBuilder1 {  
public static void main(String args[]){ 
String s= new String("java ");
s.concat("in simple way");
System.out.println(s);

StringBuffer buffer= new StringBuffer("java ");
buffer.append("in simple way");
System.out.println(buffer);

StringBuilder builder= new StringBuilder("java ");
builder.append("in simple way");
System.out.println(builder);
}  
}  




We can see that , in case of string when we perform concatenation using concat() method,it creates a new string object and its not pointed by any reference variable and variable “s” is still pointing to old string “java”.

Whereas in case of StringBuffer and StringBuilder, concat() method just modifies the same string object and hence concatenated result is displayed for them.


3) Thread safety


String is always thread safety because of its immutability feature.

It should be preferred only if there is no frequent modification, otherwise we will end up with lot of memory leakage.

As an alternative in that case, we can choose StringBuffer or StringBulder based on single threaded or multithreaded application

StringBuffer is mutable and thread safety as all the methods of this class are synchronized, so we should prefer to use it in multithreaded application

StringBuilder is mutable but not thread safe as methods of this class are not synchronized, so we should prefer to use it in single threaded application.


4) Performace


Performance of StringBuilder is far better compared to String and StringBuffer.

Consider the below code

  1. class StringBufferBuilder2 {  
  2. public static void main(String args[]){
  3.  
  4. String[] stringArray = {"java","in","simple","way"};
  5. String result = "";
  6. for (String s : stringArray) {
  7.     result = result + s;
  8. }
  9. StringBuilder builder = new StringBuilder();
  10. for (String s : stringArray) {
  11.     builder.append(s);
  12. }
  13. String result = builder.toString();
  14.  
  15. StringBuffer buffer = new StringBuffer();
  16. for (String s : stringArray) {
  17.     buffer.append(s);
  18. }
  19. String result = buffer.toString();
  20. }  
  21. }  
class StringBufferBuilder2 {  
public static void main(String args[]){

String[] stringArray = {"java","in","simple","way"};
String result = "";
for (String s : stringArray) {
    result = result + s;
}
StringBuilder builder = new StringBuilder();
for (String s : stringArray) {
    builder.append(s);
}
String result = builder.toString();

StringBuffer buffer = new StringBuffer();
for (String s : stringArray) {
    buffer.append(s);
}
String result = buffer.toString();
}  
}  


In this code, we are trying to perform concatenation inside a loop.

Performance of String will not be good here as it has to create new string for each iteration.

Performance of StringBuilder and StringBuffer will be very good compared to String as they alter the same string for each iteration without crating new object.

Between StringBuilder and StringBuffer, StringBuilder will be giving better performance as its not synchronized.

Yes, if methods are synchronized,there will be a little performance overhead.


5) hashcode and equals methods


String class has overridden hashcode() and equals() methods and 2 strings are considered as equals if their hashcode is same and also equals() method returns true.

StringBuilder and StringBuffer classes have not overridden hashcode() and equals() methods.

And it’s because they are mutable, and their primary use is for constructing strings.

If we need to compare content,we can call StringBuffer#toString() or StringBuilder#toString() and compare the returned value.

Consider below example

  1. class StringBufferBuilder3 {  
  2. public static void main(String args[]){
  3.  
  4. String s1 = new String("java");
  5. String s2 = new String("java");
  6. System.out.println(s1.equals(s2));
  7.  
  8. StringBuilder builder1 = new StringBuilder ("java");
  9. StringBuilder builder2 = new StringBuilder ("java");
  10. System.out.println(builder1.equals(builder2));
  11.  
  12. StringBuffer buffer1= new StringBuffer ("java");
  13. StringBuffer buffer2 = new StringBuffer ("java");
  14. System.out.println(buffer1.equals(buffer2));
  15. }  
  16. }  
class StringBufferBuilder3 {  
public static void main(String args[]){

String s1 = new String("java");
String s2 = new String("java");
System.out.println(s1.equals(s2));

StringBuilder builder1 = new StringBuilder ("java");
StringBuilder builder2 = new StringBuilder ("java");
System.out.println(builder1.equals(builder2));

StringBuffer buffer1= new StringBuffer ("java");
StringBuffer buffer2 = new StringBuffer ("java");
System.out.println(buffer1.equals(buffer2));
}  
}  



We can see that, though the content is same for both the objects, StringBuffer and StringBuilder returned false for equals() method

Note:

String is immutable but StringBuilder and StringBuffer are mutable

StringBuilder is not synchronized and StringBuffer is synchronized, hence StringBuilder is faster.

We can use String if we need immutability and if we have less modifications

We can use StringBuilder for mutable string without thread safety

We can use StringBuffer for mutable string with thread safety

Note down all these points to choose the right candidate in your application among String, StringBuffer and StringBuilder.

About the Author

Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on