Java Performance with Strings and StringBuilder

Strings are very frequently used in Java programs. This blog post tries to explain what a programmer needs to consider from a performance point of view. It will also explain in what situations you should use StringBuilder instead of String.

Strings in Java are immutable. If you look at the source code of String you find that java.lang.String has the following properties.

/** The value is used for character storage. */
    private final char value[];

 /** The offset is the first index of the storage that is used. */
    private final int offset;

 /** The count is the number of characters in the String. */
    private final int count;

The array is used to store the values of this String.

As Strings are immutable they can be freely shared. This property is utilized in the method substring(). The method substring will use a reference to the same String and only change the offset and the lenght value for the String. The same string is in this case used several times.

Therefore using substring requires only a constant amount of time (and almost no additional memory) and can be freely used.

The operation concat() (which is called by the + operator) combines two Strings. This method has to copy the characters of the two Strings and therefore takes time and extra space which is propotional to the length of the two strings .

The object StringBuilder has a more effectly way of concatenate Strings. It works similar to the class ArrayList by allocating a predefined array for storing the characters and keeps track of the used space. Every time the space is exceeded then it will extend the available capacity).

Does this means that you always have to use StringBuilder if you are concatening strings?

No. Of course if in your program you combine only a few times String the runtime overhead is normally not relevant for the overall performance.

But of course if you combine frequently strings in your program you should switch to StringBuilder.

About Lars Vogel

Lars Vogel is the founder and CEO of the vogella GmbH and works as Eclipse and Android consultant, trainer and book author. He is a regular speaker at international conferences, He is the primary author of vogella.com. With more than one million visitors per month this website is one of the central sources for Java, Eclipse and Android programming information.
This entry was posted in Java and tagged , . Bookmark the permalink.

13 Responses to Java Performance with Strings and StringBuilder

  1. yilmaz says:

    also stringbuilder’s methods are not thread safe. stringbuffer can be chosen when thread safety is important.

  2. Wanja says:

    note that if you are concatinating hard-coded strings, the compiler will translate it to a StringBuilder for you.
    Second, don’t use StringBuffer, it’s exactly the same as StringBuilder, but synchronised. Something you probably won’t need, but it makes it a lot slower than the StringBuilder.

  3. Silvio says:

    Which is better StringBuilder or StringBuffer to use?

  4. Chris Kessel says:

    This is far too simplistic an analysis. The compiler is smart enough to use StringBuilder for concatenations in most cases. Unless you’re concatenating over several iterations in a loop, the compiler is going to take care of this for you. A local JUG member ran tests on stuff like this and looked at the bytecode to determine behavior.

    // The compiler takes care of this with StringBuilder for you.
    String s = “asdfa” + “Asdfwe2234″ + someOtherStringObject;

    // The compiler can’t figure this out, so use StringBuilder.
    String output = “base”
    for ( String s : SomeList )
    {
    output = output + s;
    }

  5. vogella says:

    If you require thread safety you should use StringBuffer

  6. vogella says:

    @Chris I find it safer to use the correct Java construct rather then relying on the compiler. But thank you for the information, it is good to know that the compiler takes care of the simple case. Does only the Sun compiler does this or all?

  7. David Karr says:

    @Vogella:
    The Java Language Specification does not specify this behavior, but both the Sun and Eclipse Java compilers do this (converting “+” to StringBuilder usage). It’s reasonable to assume all modern Java compilers do this.

    @Wanja:
    Your first statement is slightly misleading. If you’re actually concatenating hard-coded strings, the compiler doesn’t convert it to a StringBuilder, it actually converts it directly to a string, as the compiler can do the entire computation at compile time.

    Concerning the several comments about thread safety:
    I think it’s very unlikely the “lack of thread safety” of StringBuilder would ever be an issue for anyone. This would be an issue if you had the same StringBuilder instance being accessed by multiple threads at the same time. This would be a very odd situation.

  8. vogella says:

    @David thank you for the clarifcation about the compilers.

  9. hel says:

    > Vogella says: if you require thread safety you should use StringBuffer.

    It’s only an issue if you reuse StringBuffers/-Builders stored in member variables.

    Usually you don’t reuse StringBuffers/-Builders. You create them in local scope and forget about them when leaving a method, like this:

    public String toString() {
    // Creating objects is very, very cheap.
    return new StringBuilder()
    .append(name)
    .append(“=”)
    .append(value)
    .toString();
    }

    the several threads scenario: you have several threads building a string with a single StringBuffer … this can’t be good. The resulting string is not determined. You need external synchronisation to avoid race conditions. But if you synchronize the access to StringBuffer you should use StringBuilder instead.

  10. Kirk says:

    Look at the byte code and then dump the assembler from the JIT. You’ll see that the compilers don’t always get it right. That said, I see little reason to use StringBuffer. You take the synchronization hit and most likely you’re going to only use the values in a local context.

    This benchmark was vetted by several people over a period of a couple of months http://www.infoq.com/articles/java-threading-optimizations-p1.

    Kirk

  11. Wanja says:

    @David Karr
    thnx for the correction and the good explanation.

  12. Lars, you should at least mention the quick fix to turn a concatenated string into a StringBuffer/Builder

  13. admin says:

    @Benjamin: Thanks for mentioning this! Eclipse can try a concatenated string into a StringBuilder via Ctrl+1.

Comments are closed.