String concatenation does not scale
To build Strings dynamically, one may use either the String concatenation operator + or the StringBuilder class. (StringBuilder is generally preferred over StringBuffer, since it avoids internal synchronization costs.) In the great majority of cases, only a few items are concatenated, and either style may be used freely, according to taste, without concern for performance.
On relatively rare occasions, however, when performing extensive String manipulation, replacing + with StringBuilder.append is likely recommended. Compilers often implement concatenation operations by creating intermediate objects in the background. Such intermediate objects are not needed by StringBuilder.
Cases in which + is very likely acceptable:
- if concatenating only a small number of items together, then the difference in relative performance is very small, and possibly not even measurable (the great majority of use cases of the concatenation operator fall into this category).
- in branches of code which represent a failure in the system - for example, a lost database connection, or an invalid method parameter. Since these branches are very rarely exercised, the speed at which the system fails is usually not important.
Example runs (class appears below):
Here, -Xint was used to turn off the HotSpot compiler. This ensures the program is always interpreted, and will execute in a uniform environment from start to finish, without any compilation into native code.)
Num iterations: 10 Task using + operator: 175,351 nanoseconds Task using StringBuilder.append: 35,057 nanoseconds Num iterations: 1000 Task using + operator: 18,295,297 nanoseconds Task using StringBuilder.append: 1,200,376 nanoseconds Num iterations: 10000 Task using + operator: 1,134,679,975 nanoseconds Task using StringBuilder.append: 8,757,343 nanoseconds
/** * Illustrates the speed difference between + operator and * StringBuilder.append, when performing many concatenations. */ public final class AvoidConcatenation { /** * Takes a single argument : the number of iterations to perform. */ public static void main (String... arguments) { fNumIterations = Integer.parseInt(arguments[0]); long start = System.nanoTime(); doWithConcatenationOperator(); long finish = System.nanoTime(); System.out.println("Num iterations: " + fNumIterations); StringBuilder message = new StringBuilder(); message.append("Task using + operator: "); message.append( finish - start ); message.append(" nanoseconds"); System.out.println(message); start = System.nanoTime(); doWithStringBuilder(); finish = System.nanoTime(); message = new StringBuilder("Task using StringBuilder.append: "); message.append( finish - start ); message.append(" nanoseconds"); System.out.println(message); } // PRIVATE private static int fNumIterations; private static String doWithConcatenationOperator() { String result = "start"; for (int idx = 0; idx < fNumIterations; idx++) { result = result + "blah"; } return result; } private static String doWithStringBuilder() { StringBuilder result = new StringBuilder("start"); for (int idx = 0; idx < fNumIterations; idx++) { result.append("blah"); } return result.toString(); } }
See Also :
Would you use this technique?