StringBuffers/StringBuilders for concatenation inside loops

This tip was originally written in terms of JDK 1.4 and StringBuffer. In JDK 1.5, a new class StringBuilder was introduced, which is just like StringBuffer except unsynchronized. Now you should always use StringBuilder for everything, unless you really do need the synchronization properties of StringBuffer. If you're using a variable as a temporary variable in a print method or similar, then you definitely don't need that synchronization overhead.

From: Christopher Manning 
Sender: owner-java-nlp-list@lists.Stanford.EDU
To: java-nlp-list@lists.Stanford.EDU
Subject: Thou shalt use StringBuffer for concatenation inside loops
Date: Wed, 21 Aug 2002 14:56:34 -0700

Hi, this is number one in my new occasional series of code review tips.

If you write in java:

   String str = "Type: " + t + ", class " + cl + ", value: " + value;

then Java behind the scenes makes a StringBuffer, appends all those
things in turn, and then calls the StringBuffer.toString() method which
is assigned to str (see the StringBuffer Javadoc).  This works nicely,
and you'd be stupid not to use this syntactic sugar.

However if you have something like:

    public String fullText() {
        String doc="";
        try {
            BufferedReader urlReader = new BufferedReader(new
	InputStreamReader(filterTag((InputStream)address.getContent())));
            while (urlReader.ready()) {
                doc=doc+urlReader.readLine() + "\n";
            }
        } catch (IOException e) {
            e.printStackTrace(System.err);
        }
        return doc;
    }

Then, at that inner loop line, Java will be on every iteration allocating
a StringBuffer, doing the appends on it, converting it to a String and
repeating, and performance sucks.


Now you could imagine a very clever compiler that could detect this
situation and do "Java magic" in even this case, but such a compiler
doesn't (yet) exist, and so you have to code use of the StringBuffer
yourself.  It's not that painful, as you can just chain append's:

           doc.append(urlReader.readLine()).append("\n");

Oh, and as a side tip, the no argument:

    e.printStackTrace()

sends it to System.err.

Chris.

Addendum 2005: For Java 1.5 on, in almost all circumstances (i.e., unless one requires locking for multithreading), one should now use a StringBuilder rather than a StringBuffer. A StringBuilder is identical to a StringBuffer, but unsynchronized. Otherwise the advice here remains valid.


Christopher Manning
Last modified: Fri Apr 4 20:39:48 PST 2003