Reputation: 135992
I thought that this is the most efficient way to concatinate strings
new StringBuilder(s1.length() + s2.length() + s3.length()).append(s1).append(s2).append(s3).toString();
here StringBuilder's buffer is created with the capacity enough to fit all strings in it, otherwise StringBuilder may need to expand the buffer up to 3 times.
But when I compile / decompile this
String s4 = s1 + s2 + s3;
I get the actual code in .class built by javac (1.7.0_03) as
String s4 = (new StringBuilder(String.valueOf(s1))).append(s2).append(s3).toString();
Which way is more efficient?
UPDATE
As it was suggested by Steven Schlansker, here is a performance test
String s1 = "0123456789";
String s2 = s1 + s1 + s1;
String s3 = s1 + s1 + s1 + s1 + s1 + s1;
long t0 = System.currentTimeMillis();
for (int i = 0; i < 500000; i++) {
String s4 = new StringBuilder(s1.length() + s2.length() + s3.length()).append(s1).append(s2).append(s3).toString();
// String s4 = s1 + s2 + s3;
}
System.out.println(System.currentTimeMillis() - t0);
it's not perfect, but the results seem to prove that my version is ~30% faster. On my notebook (Celeron 925) it gives ~230 ms for ver.1 aganist ~300 ms for ver.2. Actually this is what I expected. So I think it would be a good idea if javac compiled string concatination in a more efficient way. There are enough lines like
return "\\Q" + s + "\\E";
even in JDK classes. The last line is from java.util.Pattern which is designed for efficiency
Upvotes: 3
Views: 237
Reputation: 38526
Depends on the environment you execute it in. It's not possible to conclude definitely that one is better than the other without some sort of test.
That said, I agree that it's likely that knowing the final size ahead of time will provide some benefit.
I suspect that if you write a microbenchmark, you'll find that the difference is absolutely trivial in almost any application.
EDIT FOR BENCHMARK ADVICE:
I see you've added some actual data to your post. Congratulations! You're on the right track :-)
Unfortunately, Java has many features which are hostile to writing correct benchmarks. You should probably take a look at How do I write a correct micro-benchmark in Java? if you want your results to be accurate. It's also worth considering that speedups that look large in this context will look much smaller in the context of a "real" program. A single database fetch (measured in milliseconds) could easily make any gains in memory allocation completely uninteresting (measured in nanoseconds).
Upvotes: 4