Java: The difference between String, StringBuffer and StringBuilder

String: String constant
StringBuffer: String variable (thread-safe)
StringBuilder: String variable (non-thread-safe)

The difference between String and StringBuffer: The
main difference is that the content of StringBuffer is variable. In other words, if you feel that the content of the string is variable, then it is best to use StringBuffer. This can reduce memory consumption.

StringBuffer name = new StringBuffer("Name");
StringBuffer password = new StringBuffer("Password");
name.append(password);

The code is very simple, that is, two new StringBuffer classes are created. Then add the contents of the password object to the name. We follow up the append() function.

public synchronized StringBuffer append(StringBuffer sb) {
    toStringCache = null;
    super.append(sb);
    return this;
}

First of all, thread safety is achieved through the synchronized keyword. This ensures that only one thread calls append() in name.
Take a look at the variable toStringCache, which is the cache used to store the toString() method. If the StringBuffer is modified, it becomes null. Let's look at the toString() method:

public synchronized String toString() {
    if (toStringCache == null) {
        toStringCache = Arrays.copyOfRange(value, 0, count);
    }
    return new String(toStringCache, true);
}

If toStringCache is null, it will be constructed first. Then return the string.

Let’s follow up with super.append(sb); this method

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;
}

It can be seen that if sb is empty, null is returned.
If sb is not empty, get the length of sb, and then call the ensureCapacityInternal(int) function.
Let's follow up

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

It can be seen that this function first judges whether the length of value [char array] can meet the increased length. If it is not satisfied, the expandCapacity(int) method is called, and we follow up.

 void expandCapacity(int minimumCapacity) {
    int newCapacity = value.length * 2 + 2;
    if (newCapacity - minimumCapacity < 0)
        newCapacity = minimumCapacity;
    if (newCapacity < 0) {
        if (minimumCapacity < 0) // overflow
            hrow new OutOfMemoryError();
        newCapacity = Integer.MAX_VALUE;
    }
    value = Arrays.copyOf(value, newCapacity);
}

First of all, the StringBuffer class is equivalent to a Capacity, the default size is 16. Of course, you can customize the size of the Capacity when you create it. Then if the requirements are not met, we expand. Generally speaking, the expanded length is the current length*2+2, which means that there is no accident. When the length is 17, the Capacity size of the StringBuffer class is 34. And so on. However, if the expanded length is 40, it means that 34 cannot meet the requirements. So extend the length by 40, and then call the Arrays.copyOf() method to assign the value after append to value.

Only the method of append() function is mentioned here, and the implementation process of other functions is similar.

Because StringBuffer uses thread-safe technology, it runs slightly slower. And String is a character constant. It will be faster when quoted. However, if it is known that the content of the string will change, it is not considered to use String, because String constants will consume more memory.

And StringBuilder is similar to StringBuffer. The content is variable, and the implementation method is basically similar. The only difference is that StringBuilder does not implement thread-safe technology. But it also means that it will be processed faster than StringBuffer.

Guess you like

Origin blog.csdn.net/new_Aiden/article/details/50976478