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 turns 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.)
>java -cp . -Xint AvoidConcatenation 10
Num iterations: 10
Task using + operator: 0 milliseconds
Task using StringBuilder.append: 0 millisecond
>java -cp . -Xint AvoidConcatenation 100
Num iterations: 100
Task using + operator: 10 milliseconds
Task using StringBuilder.append: 0 milliseconds
>java -cp . -Xint AvoidConcatenation 1000
Num iterations: 1000
Task using + operator: 210 milliseconds
Task using StringBuilder.append: 0 milliseconds
>java -cp . -Xint AvoidConcatenation 10000
Num iterations: 10000
Task using + operator: 36913 milliseconds
Task using StringBuilder.append: 10 milliseconds
/** * 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.currentTimeMillis(); doWithConcatenationOperator(); long finish = System.currentTimeMillis(); System.out.println("Num iterations: " + fNumIterations); StringBuilder message = new StringBuilder(); message.append("Task using + operator: "); message.append( finish - start ); message.append(" milliseconds"); System.out.println(message); start = System.currentTimeMillis(); doWithStringBuilder(); finish = System.currentTimeMillis(); message = new StringBuilder("Task using StringBuilder.append: "); message.append( finish - start ); message.append(" milliseconds"); 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(); } }
|
|