0

When I use StringBuilder's append, when does the actual copying happens - when I call append() or when I evaluate the builder as a string?

I'm asking because in my application I have alot of log.debug(strA+strB+...) lines and I want to avoid evaluating the concatenations in production code. I know java optimizes the + ops and turns them to string builder appends but I don't know if the concatenation really happens or not in the append function.

2

4 Answers 4

3

StringBuilder contains an array of characters. append() adds characters to that array. Once you call stringBuilderInstance.toString() either explicitly or implicitly, then a new String instance is created based on the contents of stringbuilder.

Sign up to request clarification or add additional context in comments.

Comments

3

In StringBuilder when you append, it means you are concatenating strings. No, extra object is created internally. It is just append! When you convert StringBuilder to String using .toString(), copy of content happens from StringBuilder to String object.

Comments

1

Both. When you append to a StringBuilder you are copying characters into its internal character array. When you convert the builder to a string you copy the contents into the internal array of the String instance.

Comments

0

StringBuilder extends AbstractStringBuilder and there are several append methods inside:

public AbstractStringBuilder append(Object obj) {
    return append(String.valueOf(obj));
}

public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}


public AbstractStringBuilder append(StringBuffer sb) {
    if (sb == null)
        return appendNull();
    int len = sb.length();
    ensureCapacityInternal(count + len);
    sb.getChars(0, len, value, count);
    count += len;
    return this;
}

AbstractStringBuilder append(AbstractStringBuilder asb) {
    if (asb == null)
        return appendNull();
    int len = asb.length();
    ensureCapacityInternal(count + len);
    asb.getChars(0, len, value, count);
    count += len;
    return this;
}

@Override
public AbstractStringBuilder append(CharSequence s) {
    if (s == null)
        return appendNull();
    if (s instanceof String)
        return this.append((String)s);
    if (s instanceof AbstractStringBuilder)
        return this.append((AbstractStringBuilder)s);

    return this.append(s, 0, s.length());
}

it uses char[] value; declaration to declare storage for all characters. When you append new string, it checks current length of value array, and if it is necessary, it calls ensureCapacityInternal:

private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0)
        expandCapacity(minimumCapacity);
}

And it calls expandCapacity when it is necessary:

/**
 * This implements the expansion semantics of ensureCapacity with no
 * size check or synchronization.
 */
void expandCapacity(int minimumCapacity) {
    int newCapacity = value.length * 2 + 2;
    if (newCapacity - minimumCapacity < 0)
        newCapacity = minimumCapacity;
    if (newCapacity < 0) {
        if (minimumCapacity < 0) // overflow
            throw new OutOfMemoryError();
        newCapacity = Integer.MAX_VALUE;
    }
    value = Arrays.copyOf(value, newCapacity);
}

Conclusion: copying is calling when you append new data and the capacity of character values array is not enough to store this new data.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.