28

For string concatenation we can use either the concat() or concat operator (+).

I have tried the following performance test and found concat() is faster and a memory efficient way for string concatenation.

String concatenation comparison for 100,000 times:

String str = null;

//------------Using Concatenation operator-------------
long time1 = System.currentTimeMillis();
long freeMemory1 = Runtime.getRuntime().freeMemory();

for(int i=0; i<100000; i++){
    str = "Hi";
    str = str+" Bye";
}
long time2 = System.currentTimeMillis();
long freeMemory2 = Runtime.getRuntime().freeMemory();

long timetaken1 = time2-time1;
long memoryTaken1 = freeMemory1 - freeMemory2;
System.out.println("Concat operator  :" + "Time taken =" + timetaken1 +
                   " Memory Consumed =" + memoryTaken1);

//------------Using Concat method-------------
long time3 = System.currentTimeMillis();
long freeMemory3 = Runtime.getRuntime().freeMemory();
for(int j=0; j<100000; j++){
    str = "Hi";
    str = str.concat(" Bye");
}
long time4 = System.currentTimeMillis();
long freeMemory4 = Runtime.getRuntime().freeMemory();
long timetaken2 = time4-time3;
long memoryTaken2 = freeMemory3 - freeMemory4;
System.out.println("Concat method  :" + "Time taken =" + timetaken2 +
                   " Memory Consumed =" + memoryTaken2);

Result

Concat operator: Time taken = 31; Memory Consumed = 2259096
Concat method  : Time taken = 16; Memory Consumed = 299592

If concat() is faster than the operator then when should we use concatenation operator (+)?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sunil Kumar Sahoo
  • 53,011
  • 55
  • 178
  • 243
  • 1
    Read: http://stackoverflow.com/questions/693597/is-there-a-difference-between-string-concat-and-the-operator-in-java and http://stackoverflow.com/questions/47605/java-string-concatenation – Pankaj Kumar Jan 06 '12 at 08:21
  • About the only thing that looks different is when the string you are adding has zero length it just gives you back the original instead of creating a new String. The + operator can be a bit expensive ... if you are doing hundreds or thousands of string building operations look into StringBuffer.append(). It is common to see a method build up a StringBuffer and then return or use theBuffer.toString() at the end. – Pankaj Kumar Jan 06 '12 at 08:27
  • @PankajKumar well, you probably want StringBuilder instead of StringBuffer – ymajoros Apr 04 '13 at 07:14

8 Answers8

42

The concat method always produces a new String with the result of concatenation.

The plus operator is backed by StringBuilder creation, appending all String values you need and further toString() calling on it.

So, if you need to concatenate two values, concat() will be better choice. If you need to concatenate 100 values, you should use the plus operator or explicitly use StringBuilder (e.g. in case of appending in a cycle).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Artem
  • 4,347
  • 2
  • 22
  • 22
  • 4
    Your latter comment is only true for all string concatenations that are in the **same expression**. So one `StringBuilder` is used for `x = a + b + c` (assuming all are `String`s), but two `StringBuilder`s are used for `x = a + b; x += c;`. – T.J. Crowder Jan 06 '12 at 08:16
  • 1
    As an addendum to Artem's answer, [this](http://www.znetdevelopment.com/blogs/2009/04/06/java-string-concatenation/) link, which appears to be a blog post from back in '09 regarding this specific question. Hopefully the link will give some more context for the answers and comments that Artem and TJ have provided, though I can't verify the assertions made in the article as I'm admittedly no expert on Java myself... – blahman Jan 06 '12 at 08:20
  • 2
    Don't you mean `explicitly use StringBuilder` – RokL Jan 06 '12 at 08:20
  • Thank you, my English is far from brilliant :-) – Artem Jan 06 '12 at 08:29
  • "Concat method always produces a new String with result of concatenation." No, it does not: `if (otherLen == 0) {return this;}` – Thilo Jan 06 '12 at 08:40
  • concat() does not "always" produce new String. See java docs for concat(). if length argument string is 0 then it returns same string as shown in above comment of Thilo also. – a Learner Nov 20 '12 at 05:31
13

In fact s1 + s2 and s1.concat(s2) are very different.

s1 + s2 is converted by javac into

(new StringBuilder(String.valueOf(s1)).append(s2).toString();

You can see it if you decompile .class. This construct is not very efficient; it involves up to three new char[] allocations and three char[] copy operations.

s1.concat(s2) is always one new char[] + one copy operation, see String.java

public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    char buf[] = new char[count + otherLen];
    getChars(0, count, buf, 0);
    str.getChars(0, otherLen, buf, count);
    return new String(0, count + otherLen, buf);
}

Note that new String(int, int, char[]) is String's package private constructor. It uses char buf[] directly, without the usual copying to ensure the buf invisibility for the String immutability.

logi-kal
  • 7,107
  • 6
  • 31
  • 43
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • 2
    I wonder why javac uses `StringBuilder` even when combining fewer than four strings? I would think `String.valueOf(strA).concat(strB).concat(strC)` would generate code that was more compact and--for every combination of string lengths--faster than what `strA+strB+strC` actually generates, unless the JITter replaces code that calls `StringBuilder` with something more efficient. – supercat Feb 03 '15 at 17:21
7

Your test needs to be running for at least 2 seconds with each loop in a separate method to be meaningful. Short tests can be every difficult to reproduce and compare. From your timing it appears you are using Windows (i.e. because you times are 16 and 31 ms ;) Try System.nanoTime() instead. When your loop iterates over 10,000 times the whole method is compiled. This means your later method is already compiled when it is started.

In answer to your question concat is marginally faster when adding two Strings. However, it comes with a typing and conceptual overhead which is likely to be much greater than the CPU you save. Even based on your tests repeating 100,000 times it saves less than 15 ms, and yet it cost you far, far more than that in your time (which is likely to be worth more) You could find in a future version of the JVM, the difference is optimised always and the complexity of your code is still there.


EDIT: I didn't notice that the memory result was suspect.

String str = null;

//------------Using Concatenation operator-------------
long time1 = System.currentTimeMillis();
long freeMemory1 = Runtime.getRuntime().freeMemory();
for (int i = 0; i < 10000; i++) {
    str = "Hi";
    str = str + " Bye";
}
long time2 = System.currentTimeMillis();
long freeMemory2 = Runtime.getRuntime().freeMemory();

long timetaken1 = time2 - time1;
long memoryTaken1 = freeMemory1 - freeMemory2;
System.out.println("Concat operator  :" + "Time taken =" + timetaken1 + " Memory Consumed= " + memoryTaken1);

str = null;
//------------Using Concat method-------------
long time3 = System.currentTimeMillis();
long freeMemory3 = Runtime.getRuntime().freeMemory();
for (int j = 0; j < 10000; j++) {
    str = "Hi";
    str = str.concat(" Bye");

}
long time4 = System.currentTimeMillis();
long freeMemory4 = Runtime.getRuntime().freeMemory();

long timetaken2 = time4 - time3;
long memoryTaken2 = freeMemory3 - freeMemory4;
System.out.println("Concat method  :" + "Time taken =" + timetaken2 + " Memory Consumed= " + memoryTaken2);

prints when run with -XX:-UseTLAB -mx1g

Concat operator  :Time taken =12 Memory Consumed= 1291456
Concat method  :Time taken =7 Memory Consumed= 560000

making the ratio of memory usage about 2:1. In the original question the result vary every time you run it, sometimes the .concat() appears to use more.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • "yet it cost you far, far more than that in your time (which is likely to be worth more)" here cost means typing and conceptual overhead ? But if we ignore 15ms benefit, one can argue that memory usage is 1/10th – lowLatency Mar 16 '13 at 10:15
  • @Naroji I can't see how the memory is 1/10th, 15ms is the time it take to press one key and is trivial really in terms of development time. – Peter Lawrey Mar 16 '13 at 21:26
  • memory consumed is 1/10th, as mentioned in the question also. Concat operator :Time taken =31 Memory Consumed ="2,259,096" Concat method :Time taken =16 Memory Consumed ="299,592" – lowLatency Mar 16 '13 at 23:12
  • The 60 Hz (~16.66 ms) tick counter? – Peter Mortensen Jul 09 '19 at 17:16
3

I believe the 'style' of concatenation is going to make a difference.

For concat(), it internally creates a new char array buffer, and returns a new string based on that char array.

For the + operator, the compiler in fact translate it to use StringBuffer/StringBuilder.

Therefore, if you are concatenating two strings, concat() is definitely a better choice because the number of objects created is only the result String (and the char buffer used inside), while using the + operator will be translated to:

result = strA + strB;
-- translate to -->
result = new StringBuilder(strA).append(strB).toString();

An extra StringBuilder instance is created.

However, if you are concatenating, for example five strings in a row, each concat() will create a new String object. While using the + operator, the compiler will translate the statement to one StringBuilder with multiple append operations. It is definitely saving a lot of unnecessary temporary object instance:

result = strA + strB + strC + strD + strE;
-- translate to -->
result = new StringBuilder(strA).append(strB).append(strC).append(strD).append(strE).toString();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
  • The break-even point is roughly four strings; the relative efficiency of `(String.valueOf(strA).concat(strB)).concat(String.valueOf(strC).concat(strD))` versus using a string builder is roughly a toss-up. For up to eight strings, concatenation might be slower, but never hugely so, and is likely to be faster in the cases where it would matter (it will end up copying each character exactly three times; `StringBuilder` will copy each character twice if it never has to expand, but if strings are large expansion will likely be required). – supercat Feb 03 '15 at 17:14
0

You can always use + if only you use >= Java 1.5 and you don't declare your base String (that you want concatenate) outside of the loop. In Java 1.5 it results in creating new StringBuilder and working on it till your string is complete. That's the fastest way.

Anyway - if you are in a loop (and concatenating strings with +) - every iteration of the loop creates a new StringBuilder - that's not the best idea. So this is where you should force the use of StringBuilder or StringBuffer (thread safe) classes.

Generally, this link clearly answers your question, and gives you complete knowledge:

http://littletutorials.com/2008/07/16/stringbuffer-vs-stringbuilder-performance-comparison/

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
dantuch
  • 9,123
  • 6
  • 45
  • 68
0

Though both the operator and the method are giving the same output, the way they work internally differs.

The concat() method that just concatenates str1 with str2 and outputs a string, is more efficient for a small number of concatenations.

But with concatenation operator '+', str1+=str2; will be interpreted as str1 = new StringBuilder().append(str1).append(str2).toString();

You can use the concat method when using a fewer number of strings to concatenate. But the StringBuilder method would be fast in terms of performance, if you are using a large number of strings.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Manikandan Sigamani
  • 1,964
  • 1
  • 15
  • 28
  • Constructing one string builder and using it repeatedly is good for performance, but creating a string builder, using it to join fewer than four strings, and then abandoning it is counterproductive. Unfortunately, the compiler often uses and abandons string builders after using them to join two strings. – supercat Feb 03 '15 at 17:08
-2

Actually, both are the same. If you see the code of concat(String paramString) it will return a new object of string, and in the (+) operator it it will also generate a new string object.

If you don't want to create a new object then use string builder to concatenate two strings.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ashish
  • 1,527
  • 4
  • 17
  • 33
-2

In general it is a bad practice to concatenate Strings with + and with concat(). If you want to create a String use StringBuilder instead.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Christian Kuetbach
  • 15,850
  • 5
  • 43
  • 79
  • This is obviously a wrong answer. There are many case that we should use + or concat() instead of StringBuilder/StringBuffer. – Adrian Shum Aug 07 '13 at 01:49
  • The case showed in the question was concatenation of string in a loop, in that case I believe StringBuilder is the best way to go, not only in Java. – Felype Jun 06 '17 at 16:27