When we think about String Concatenation in Java, what comes to our mind is the + operator, one of the easiest ways to join two String or a String, and a numeric in Java. Since Java doesn't support operator overloading, it's pretty special for String to have behavior. But in truth, it is the worst way of concatenating String in Java. When you concatenate two String using + operator e.g. "" + 101, one of the popular ways to convert int to String, compiler internally translates that to StringBuilder append call, which results in the allocation of temporary objects.
You can see the real difference in the performance of our example program, in which we have concatenated 100,000 String using the + operator. Anyway, this article is not just about + operator but also about other ways to concatenate multiple Strings.
There are four ways to do this, apart from the + operator, we can useStringBuffer,StringBuilder, andconcat() method fromjava.lang.String class for the same purpose.
BothStringBuilder andStringBuffer classes are there for just this reason, and you can see that in our performance comparison.StringBuilder is the winner and the fastest way to concatenate Strings. StringBuffer is a close second, because of the synchronized method, and the rest of them are just 1000 times slower than them.
BothStringBuilder andStringBuffer classes are there for just this reason, and you can see that in our performance comparison.StringBuilder is the winner and the fastest way to concatenate Strings. StringBuffer is a close second, because of the synchronized method, and the rest of them are just 1000 times slower than them.
4 ways to concatenate String in Java
Here we will see examples of all four ways of concatenating Strings in Java. Starting with the most popular approach, joining string using + operator.
1. String Concatenation using + Operator
The easiest way of joining multiple String and numeric values in Java. Just remember that, when you have two or more primitive type values e.g. char, short, or int, at the beginning of your string concatenation, you need to explicitly convert the first of them to a String.For exampleSystem.out.println(200 + 'B' + ""); will not print200B, instead, it will print266, by taking ASCII values of'B' and adding them to 200.
On the other handSystem.out.println("" + 200 + 'B')will print200B. Unfortunately, this is the worst way to concatenate String in Java. Let's take a look athow the String concatenation operator works in Java. When we write :
it's translated into
All + operator are translated into severalStringBuilder.append() calls before finaltoString() call.
SinceStringBuilder(String) constructor allocates a buffer with only 16 char, appending more than 16 characters will require buffer reallocation. At last,StringBuffer.toString() calls create a new String object with a copy of the StringBuilder buffer.
This means, to concatenate two String, you will need to allocate, oneStringBuilder, one char array[16], one String object and another char[] of appropriate size to fit your input value. Imagine if you are doing these thousands of times in your application, it's not only slow but also increases the workload of Garbage Collector.
You can also see Java Performance The Definitive Guide By Scott Oaks to learn more about how to do performance testing in Java and how to tune different things in the Java ecosystem to get the best performance from your Java application.
The performance ofconcat() method is similar to the + operator and I don't recommend using it for any production purpose.
On the other handSystem.out.println("" + 200 + 'B')will print200B. Unfortunately, this is the worst way to concatenate String in Java. Let's take a look athow the String concatenation operator works in Java. When we write :
String temp=""+200+'B';
it's translated into
newStringBuilder().append("" ).append(200 ).append('B').toString();
All + operator are translated into severalStringBuilder.append() calls before finaltoString() call.
SinceStringBuilder(String) constructor allocates a buffer with only 16 char, appending more than 16 characters will require buffer reallocation. At last,StringBuffer.toString() calls create a new String object with a copy of the StringBuilder buffer.
This means, to concatenate two String, you will need to allocate, oneStringBuilder, one char array[16], one String object and another char[] of appropriate size to fit your input value. Imagine if you are doing these thousands of times in your application, it's not only slow but also increases the workload of Garbage Collector.
You can also see Java Performance The Definitive Guide By Scott Oaks to learn more about how to do performance testing in Java and how to tune different things in the Java ecosystem to get the best performance from your Java application.
2. Using concat() method from java.lang.String
Concat(String str)method concatenates the specified String to the end of this string. I have hardly seen this used for concatenation, though. Inside, it allocates achar[] of length equal to the combined length of two String, copies String data into it, and creates a new String object using private String constructor, which doesn't make a copy of inputchar[], as shown below.publicString concat(String str) {int otherLen= str.length();if (otherLen==0) {returnthis; }int len= value.length;char buf[]=Arrays.copyOf(value, len+ otherLen); str.getChars(buf, len);returnnewString(buf,true); }/* * Package private constructor which shares value array for speed. * this constructor is always expected to be called with share==true. * a separate constructor is needed because we already have a public * String(char[]) constructor that makes a copy of the given char[]. */ String(char[] value,boolean share) {// assert share : "unshared not supported";this.value= value; }
The performance ofconcat() method is similar to the + operator and I don't recommend using it for any production purpose.
3. Using StringBuffer
This was the proper way to concatenate multiple String, integer, and others prior to Java 5 when StringBuilder was not available. It's much faster than the + operator andconcert() method. The only drawback of this class is that all itsappend methods are synchronized.Since we hardly share temporary string in a concurrent environment, the price for thread-safety is not desired in many cases, that's where StringBuilder is used.
It works similarly to StringBuilder synchronization. It also provides several overloadedappend() methods to concatenate integer, char, short, etc.
4. Using StringBuilder
This is the best way to concatenate String in Java, especially when you are concatenating multiple Strings. It's not thread-safe, but you hardly need that during String concatenation. In the next section, we will see a performance comparison of all these 4 ways to concatenate String in Java.From JDK 8 onwards, you can also use StringJoiner to concatenate in Java. I am not including StringJoiner in this article but you can also these10 examples of StringJoiner to learn more about it.
Performance comparison + Operator vs Concat vs StringBuffer vs StringBuilder
here is a sample Java program to find out which method gives us best performance for String concatenation.publicclassDemo{publicstaticvoid main(String args[]) throws IOException { finalint ITERATION= 100_000;String s="";// String Concatenation using + operator long startTime=System.nanoTime();for (int i=0; i < ITERATION; i++) { s= s+ Integer.toString(i); } longduration= (System.nanoTime()- startTime)/1000;System.out.println("Time taken to concatenate 100000 Strings using + operator (in micro) : "+duration);// Using String concat() method startTime=System.nanoTime();for (int i=0; i < ITERATION; i++) { s.concat(Integer.toString(i)); }duration= (System.nanoTime()- startTime)/1000;System.out.println("Time taken to concatenate 100000 Strings using concat method (in micro) : "+duration);// StringBuffer example to concate String in Java StringBuffer buffer=new StringBuffer();// default size 16 startTime=System.nanoTime();for (int i=0; i < ITERATION; i++) { buffer.append(i); }duration= (System.nanoTime()- startTime)/1000;System.out.println("Time taken to concatenate 100000 Strings using StringBuffer (in micro) : "+duration);// StringBuilder example to concate two String in Java StringBuilder builder=new StringBuilder(); //default size for worst case startTime=System.nanoTime();for (int i=0; i < ITERATION; i++) { builder.append(i); }duration= (System.nanoTime()- startTime)/1000;System.out.println("Time taken to concatenate 100000 Strings using StringBuilder append in micro) : "+duration); }}Output:Time taken to concatenate100000 Strings using+ operator (in micro):29178349Time taken to concatenate100000 Strings usingconcatmethod (in micro):21319431Time taken to concatenate100000 Strings using StringBuffer (in micro):12557Time taken to concatenate100000 Strings using StringBuilder append (in micro):10641
You can clearly see that given everything the same, StringBuilder outperforms all others. It's almost 3000 times faster than + operator.concat() method is better than + operator but still very bad compared to StringBuffer and StringBuilder.
StringBuffer took more time thanStringBuilder because of synchronized method. I know that, you hardly join 100K Strings but even for small numbers it adds. if you run program to join just 10 Strings, you will notice significant difference in time spent Here is what I got when I ran this program for 10 iteration only :
Though using the + operator along withempty String is easiest and obvious way to concatenate multiple String and numeric in Java, you should not use that, especially inside loops. Always use StringBuilder for string concatenation, the class is there for a reason, and if you are still using StringBuffer then get rid of that, because most of the time you don't really need the thread-safety overhead of StringBuffer.
+ operator took (in micros):177concat() method took (in micros):28StringBuffer took (in micros):21StringBuilder append took (in micros):8
Though using the + operator along withempty String is easiest and obvious way to concatenate multiple String and numeric in Java, you should not use that, especially inside loops. Always use StringBuilder for string concatenation, the class is there for a reason, and if you are still using StringBuffer then get rid of that, because most of the time you don't really need the thread-safety overhead of StringBuffer.
Unfortunately, concat() method is only good when you need to concatenate exactly 2 strings. In short, always useStringBuilder to concatenate Strings in Java.
If you like this tutorial and want to learn more about String class in Java, check out these amazing String tutorials from Java67 blog :
If you like this tutorial and want to learn more about String class in Java, check out these amazing String tutorials from Java67 blog :
- How to convert Enumeration type to String in Java
- How to check if a String contains one number in Java
- ArrayList to String in Java
- Difference between StringBuilder and StringBuffer in Java
- How to find if String is Empty in Java
- How to convert array to String in Java
- How to reverse String in Java
- Difference between String object and literal in Java
- Difference between String and StringBuffer in Java
- Best way to compare two Strings in Java
- How to remove whitespace form String in Java
Over to you, what is your favorite way to concatenate String in Java? Plus operator, StirngBuffer, StringBuilder, StringJoiner or anything else?
From Java >1.6 plus operator is changed into StringBuilder by compiler. So what is the point in making code less readable by StringBuilder?
ReplyDelete@Michal, there are cases where using + operator is not optimal e.g. concatenating in loop, because Java will internally create and destroy StringBuilder instances. Sometime its better to have one StringBuilder object outside loop and just append on it while iterating over loop, instead of using + operator.
DeleteYes there are cases, but these will make about 0.000000000001% of cases; making the explicit use of stringbuilder just a waste of time (and an unneeded premature optimization)
DeleteIt depends on one's preferences and/or string you are creating but using StringBuilder might be far more readable than + operator.
DeleteI ran your code and got similar results. However, when I added a couple more cases, I was surprised:
ReplyDeleteCase 1 - building a new string using '+'. (s = "one" + 2 + 3.0;)
Case 2 - build a new string using StringBuilder (s = new StringBuilder().append("one").append(2).append(3.0).toString();)
These results were MUCH different from your examples of *appending* to an existing string. In fact, using the '+' method was 100 times faster!
Hi, I added the String.join method like this:
ReplyDeletestartTime = System.nanoTime();
for (int i = 0; i < ITERATION; i++) {
s = String.join(" ", Integer.toString(i));
}
duration = (System.nanoTime() - startTime) / 1000;
System.out
.println("Time taken to concatenate 100000 Strings using String.join in micro) : " + duration);
it was much faster than concat and closer to the StringBuilder
final int ITERATION = 100_0;
ReplyDeleteits giving strange result. Making StringBuffer fastest ?
Time taken to concatenate 100000 Strings using + operator (in micro) : 9053
Time taken to concatenate 100000 Strings using concat method (in micro) : 3796
Time taken to concatenate 100000 Strings using StringBuffer (in micro) : 469
Time taken to concatenate 100000 Strings using StringBuilder append in micro) : 485
Hello Shashank, which version of JDK you are using? StringBuffer is not really a problem in single threaded environment because uncontented lock acquisition has become faster with latest JVM and JIT version.
ReplyDeleteAny analysis on String.format?
ReplyDeleteA few corrections to make the test fair.
ReplyDelete1. Both StringBuilder and StringBuffer need to produce their merged string result by calling toString() inside the timing fence.
2. The concat call also needs to save its result as in:
s = s.concat(i);
3. The working String s needs to be reset prior to each test that uses it.
s = "";
4. Appending an integer to a String is not a good test of the string functions. It is possible a bulk of the time measured will be the conversion of the integer to a string. This conversion is constant on all the tests. I would recommend appending a constant String value rather then a converted integer.
5. I find StringBuilder surprisingly inefficient with its memory management. It is filling a regrowing array of character array rather then a single pass merging all of the results. If you want to reduce your memory hit and your source strings are persistent (not coming from a file or stream), you may want an alternate solution like:
http://landenlabs.com/android/weakness/java-weakness.html#java.stringbuilder
Lastly - I find all good benchmarks should verify the functions are producing identical results. The testing should include the display of a hash code of the function results.
how to concat
ReplyDelete(what)
and (is java?)
so that the output will be as ( what is java )...
In method 2, what is variable value refers to ?
ReplyDeleteHello giri, it refers to instance variable value in the String class. See the full code from java.lang.String class in Eclipse.
Delete