Bad Advice - Always Use a StringBuffer to Concatenate

This advice is doubly wrong.

Firstly it advocates using the synchronized StringBuffer rather than a StringBuilder.

Secondly it is an oversimplification or misunderstanding of the more nuanced and reasonable advice to not concatenate Strings in a loop.

Avoiding concatenation in a loop is reasonable. Using a StringBuilder is likely to be more efficient if the loop executes a reasonable number of times as it will avoid string allocations.

The performance difference is unlikely to be significant in most cases, but the resulting code isn't noticeably less-readable - so it is a premature optimization without a cost.

Lets see what happens when we apply this advice when no loop is present:

  public String buffer(String s, int i) {
    StringBuilder sb = new StringBuilder();
    sb.append("Foo");
    sb.append(s);
    sb.append(i);
    return sb.toString();
  }

  public String concat(String s, int i) {
    return "Foo" + s + i;
  }

The concat version is far clearer.

Is it less efficient?

The eclipse compiler generates the following bytecode for concat:

    NEW java/lang/StringBuilder
    DUP
    LDC "Foo"
    INVOKESPECIAL java/lang/StringBuilder.<init> (Ljava/lang/String;)V
    ALOAD 1
    INVOKEVIRTUAL java/lang/StringBuilder.append /
       (Ljava/lang/String;)Ljava/lang/StringBuilder;
    ILOAD 2
    INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
    ARETURN

A StringBuilder is created by the compiler behind the scenes to handle the concatenation so our simpler cleaner code produces identical bytecode to the more verbose option.

The presence of loops in the code may prevent the compiler performing this optimization, but code without branches will be optimized every time. Although compilers may exist that do not support this optimization it is unlikely that you will ever use them.

results matching ""

    No results matching ""