Java--String "+", StringBuffer and StringBuilder

Posted by Micah D on Thu, 17 Feb 2022 05:04:00 +0100

1, String

String: string constant. The length of the string is immutable. In Java, string is immutable

The underlying code of String is a char array decorated with final. After defining a String variable, the content of the variable is immutable

We can view the source code as follows:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    
    ......
}

Because strings are immutable in Java, every time you use "+" to splice strings, a new character substitution will be generated in the character creation constant pool,

Moreover, these three objects have never lost their references, so the JVM cannot garbage collect, which will occupy a lot of memory in the method area and waste a lot of memory resources.

For example:

String str = "hello" + "world";

The above line of code to create a string creates three string objects, "hello", "world", "helloworld"

String and StringBuffer, memory diagram of StringBuilder object

2, StringBuffer

StringBuffer(JDK1.0)

StringBuffer: String variable (Synchronized, thread safe). Frequently modify the String content. For efficiency reasons, it is best to use StringBuffer. If you want to convert to String type, you can call the toString() method of StringBuffer.

Source code:

public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{
    /**
     * A cache of the last value returned by toString. Cleared
     * whenever the StringBuffer is modified.
     */
    private transient char[] toStringCache;


    /**
     * Constructs a string buffer with no characters in it and an
     * initial capacity of 16 characters.
     */
    public StringBuffer() {
        super(16);
    }


    @Override
    public synchronized int length() {
        return count;
    }

    @Override
    public synchronized int capacity() {
        return value.length;
    }

    @Override
    public synchronized StringBuffer append(Object obj) {
        toStringCache = null;
        super.append(String.valueOf(obj));
        return this;
    }

    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
}

When using the StringBuffer class, you will operate on the StringBuffer object itself every time instead of generating a new object. Therefore, if you need to modify the string, it is recommended to use StringBuffer.

In the source code, you can see that many methods are decorated with the keyword "synchronized", so they are thread safe!

The StringBuilder class is proposed in Java 5. The biggest difference between it and StringBuffer is that the StringBuilder method is not thread safe (cannot be accessed synchronously).

StringBuffer and StringBuilder are abstract classes that inherit from AbstractStringBuilder

3, StringBuilder

StringBuilder(JDK5.0)

StringBuilder: string variable (non thread safe). Method usage is similar to StringBuffer

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{

    /**
     * Constructs a string builder with no characters in it and an
     * initial capacity of 16 characters.
     */
    public StringBuilder() {
        super(16);
    }

    @Override
    public StringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }

    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
}

4, The difference between String, StringBuffer and StringBuilder

Through the underlying code, we can see that String is an immutable object. Therefore, every time the String type is changed, a new String object will be generated, and then the pointer will point to the new String object. Therefore, it is better not to use String for strings that often change content, because each generation of object will affect the system performance, Especially when there are many non reference objects in memory, the GC of the JVM will start to work and the performance will be reduced.

When StringBuilder and StringBuffer splice strings, they judge whether the string length is enough, so as to create a new array to encapsulate data, while the original object is abandoned for reference and waiting for garbage collection, so as to reduce the waste of memory

5, Use

1. Basic principles:

(1) If you want to manipulate a small amount of data, use String

(2) Single thread operation of a large amount of data, using StringBuilder

(3) Multithreading operates a large amount of data, using StringBuffer

2. Do not use the "+" of String class for frequent splicing. For such poor performance, you should use StringBuffer or StringBuilder class

3. For better performance, when constructing StringBuffer or StringBuilder, you should specify their capacity as much as possible. If the string length of the operation does not exceed 16 characters, it is unnecessary. When the capacity is not specified, an object with a capacity of 16 is constructed by default. Not specifying capacity can significantly degrade performance.

4. StringBuilder is generally used inside the method to complete similar + functions. Because it is thread unsafe, it can be discarded after use. StringBuffer is mainly used in global variables.

5. In the same case, using StringBuilder can only improve the performance by about 10% ~ 15% compared with using StringBuffer, but it takes the risk of unsafe multithreading. The first mock exam is not always able to clearly determine whether the module will be run in a multithreaded environment. Therefore, unless the system's bottleneck is determined on StringBuffer and the module is not running in multithread mode, StringBuilder can be used. Otherwise, use StringBuffer.

Reference articles

Differences between Java String, StringBuffer and StringBuilder

Topics: JavaSE StringBuffer StringBuilder