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:

Here's an illustration of the difference in execution speed between + and StringBuilder.append, when performing many concatenations. Clearly, even the + operator is quite fast, and the difference is not going to be noticeable in the great majority of cases encountered in practice.

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 :
Implementing toString
Time execution speed
Would you use this technique?
Yes   No   Undecided   
© 2014 Hirondelle Systems | Source Code | Contact | License | RSS
Individual code snippets can be used under this BSD license - Last updated on September 21, 2013.
Over 2,000,000 unique IPs last year - Built with WEB4J.
- In Memoriam : Bill Dirani -