Detailed explanation of StringBuilder and StringBuffer (differences, usage methods, including source code explanation)


Table of contents

1. Why use StringBuilder and StringBuffer

String immutability

Performance loss

2. StringBuilder and StringBuffer

StringBuffer source code explanation

Usage

3. Summary of common methods

Example: 

4. The difference between StringBuilder and StringBuffer


1. Why use StringBuilder and StringBuffer

Before introducing StringBuilder and StringBuffer, we can review our previous string splicing operations. Most of them are spliced ​​directly as follows:

    public static void main(String[] args) {
        String s = "hello";
        s += " world";
        System.out.println(s); // 输出:hello world
    }

 There is certainly no problem with such an operation, but if we talk about efficiency, the efficiency of such code is very low. Why is it so low? At this point we have to mention the related properties of strings.

String immutability

The String class is immutable when designed. We can see the following comments in the source code of JDK1.8

Therefore, the methods we usually use to operate String strings are to create a new object for operation. It is also very simple to verify this conclusion. We can choose a method at will. We use < a i=1>“ == ” is equivalent to comparing the hash values ​​of the addresses of both variables, We compare a string with a string converted to uppercase 

    public static void main(String[] args) {
        String s = "hello";
        //s.toUpperCase(Locale.of(s));
        System.out.println( s == s.toUpperCase(Locale.of(s)));
    }

 Output result:

Performance loss

Let’s review the splicing operation of strings just now. Each splicing requires a new object. When the number of splicings is very large, it will cause very serious performance problems. Of course, we can also verify this performance problem by using the currentTimeMillis method. To directly get the timestamp of the current system, we can use a loop to show the performance loss of using the traditional method of splicing strings.

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        String s = " ";
        for(int i = 0; i < 10000; ++i){
            s += i;
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }

Output result:

Of course, this is only 10,000 cycles, resulting in a running time of 82 milliseconds. The number of cycles required in actual projects is often immeasurable, so splicing in this way often cannot meet our performance requirements.


2. StringBuilder and StringBuffer

In order to solve the above problems, we can use StringBuilder and StringBuffer< a i=4> to perform string splicing and other operations. We can open API to see what StringBuilder and StringBuffer are

StringBuilder:

 StringBuffer:

StringBuffer source code explanation

In general use, their functions are roughly the same. Here the author will only choose one of them for explanation. The overall methods and techniques used are mostly the same, so there is no need to worry about incomplete knowledge coverage. , the author takes  StringBuffer as an example. We can use IDEA Open the source code of StringBuffer , we can find that it is also modified by final , Inherits the parent class AbstractStringBuilder and implements part of the interface

There are two member variables in parent classAbstractStringBuilder :  

We can see that its construction method contains operations corresponding to different initializations:

Usage

By combining the super keyword in the source code with the member variables in the above parent class, we can get the following conclusion: We create a new one by default When a  StringBuffer  is actually created, a new one 16 bytes is created Array, we can also use the other two construction methods to directly pass in the size parameter or directly pass in a string when passing parameters

We summarizethree commonly used initialization methodsas follows:

  • No parameters are passed, the default size is 16 bytes array
  • Directly declare the size by passing in parameters
  • Pass in string
        StringBuffer stringBuffer1 = new StringBuffer();
        StringBuffer stringBuffer3 = new StringBuffer(20);
        StringBuffer stringBuffer2 = new StringBuffer("hello");

3. Summary of common methods

The biggest feature of ourStringBuilder and StringBuffer is They are internally variable. When we operate strings through these two classes, we do not need to create a new object. Therefore, we often use these two classes when splicing strings. This is extremely To a large extent, it helps us improve the efficiency of process operation

Let’s talk about the example mentioned at the beginning of the article again. We use StringBuffer’s append StringBuffer The a> here to compare the time required to splice characters. StringBuffer method can directly splice characters. We use traditional splicing characters and the

    public static void main(String[] args) {
        
        long start = System.currentTimeMillis();
        String s = "";
        for(int i = 0; i < 10000; ++i){
            s += i;
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);

        System.out.println("=======分割行========");

        start = System.currentTimeMillis();
        StringBuffer sbf = new StringBuffer("");
        for(int i = 0; i < 10000; ++i){
            sbf.append(i);
        }
        end = System.currentTimeMillis();
        System.out.println(end - start);

    }

Output result:

We can intuitively find that using  StringBuffer  to splice characters is more efficient than direct splicing Dozens of times, and if more cycles are added, this multiple can continue to increase. It is not a dream to increase the efficiency of the original program hundreds of times< /span>

In addition to the aboveappen method, we summarize the commonly used methods as follows:

method illustrate
StringBuff append(String str)
Additional part, equivalent value String target += , Possible to add: boolean , char , < a i=9>char[] , double, float, int< /span>, < /span>change amountStringBuff, StringObject, long,
char charAt(int index)
Get the character at index position
int length()
Get the length of a string
int capacity()
Get the total size of the underlying storage string space
void ensureCapacity(int mininmumCapacity)
Expansion
void setCharAt(int index, char ch)
Set the character at index to ch
int indexOf(String str)
Return str The first occurrence of position
int indexOf(String str, int fromIndex)
Search from fromIndex position str for the first time where it appears
int lastIndexOf(String str)
Returns the position of the last occurrence str
int lastIndexOf(String str, int fromIndex)
Start from fromIndex and find the last occurrence of str location
StringBuff insert(int
offset, String str)
Insert at position offset : eight base class types & String< a i=4>Type & ObjectType Data
StringBuffer deleteCharAt(int index)
删切 index Position mark
StringBuffer delete(int start, int end)
Delete [start, end) Characters in the range
StringBuffer replace(int start, int end, String str)
Replace the characters at [start, end) with str
String substring(int start)
Start start and end with characters String return
String substring(int start, int end)
Convert [start, end) to String return
StringBuffer reverse()
Reverse a string
String toString()
Return all characters as String

Example: 

    public static void main(String[] args) {

        StringBuilder sb1 = new StringBuilder("hello");
        StringBuilder sb2 = sb1;
        // 追加:即尾插-->字符、字符串、整形数字
        sb1.append(' '); // hello
        sb1.append("world"); // hello world
        sb1.append(123); // hello world123
        System.out.println(sb1); // hello world123
        System.out.println(sb1 == sb2); // true
        System.out.println(sb1.charAt(0)); // 获取0号位上的字符 h
        System.out.println(sb1.length()); // 获取字符串的有效长度14
        System.out.println(sb1.capacity()); // 获取底层数组的总大小
        sb1.setCharAt(0, 'H'); // 设置任意位置的字符 Hello world123
        sb1.insert(0, "Hello world!!!"); // Hello world!!!Hello world123
        System.out.println(sb1);
        System.out.println(sb1.indexOf("Hello")); // 获取Hello第一次出现的位置
        System.out.println(sb1.lastIndexOf("hello")); // 获取hello最后一次出现的位置
        sb1.deleteCharAt(0); // 删除首字符
        sb1.delete(0, 5); // 删除[0, 5)范围内的字符
        String str = sb1.substring(0, 5); // 截取[0, 5)区间中的字符以String的方式返回
        System.out.println(str);
        sb1.reverse(); // 字符串逆转
        str = sb1.toString(); // 将StringBuffer以String的方式返回
        System.out.println(str);
        
    }

As can be seen from the above examples: String and StringBuilderThe biggest difference is that the content of String cannot be modified, while the content of StringBuilder can be modified, so consider using < if strings are frequently modified. a i=7>StringBuilder

Note: String and StringBuilder classes cannot be converted directly. If you want to convert each other, you can adopt the following principles:

  • String becomes StringBuilder: Use StringBuilder’s construction method or append() method
  • StringBuilder becomes String: CalltoString()method

4. The difference between StringBuilder and StringBuffer

We can open the source code ofStringBuffer, and we observe that almost everyStringBuffer There is one in front of synchronized to modify StringBuffer , heresynchronized can actually be understood as a lock, which issynchronized Modified methods are not allowed to be called by multiple objects at the same timeat the same time. This setting is for the safety of multi-threaded programs.

To give a popular example: Xiao Wang, Xiao Li, and Xiao Hong want to go to the toilet, but there is only one toilet. Xiao Wang goes to the toilet first, then Xiao Li or Xiao Hong can only wait for Xiao Wang to use the toilet and come out. After that, you can go to the toilet

And ourStringBuffer is set up like this. When an object is called, it issynchronized When a> modifies the method, this method will be locked and cannot be used by other objects. Only after the current object has used this method, that is, after it is unlocked, other objects can access it

When we open the source code ofStringBuilder we will find our StringBuilderThere is no such setting operation

Summarize:

That is to sayStringBuffer is for the safety of multi-threads, but frequent locking and unlocking will reduce the running efficiency of the code, and a>StringBuilder, if it is for high efficiency, useStringBufferAlthough there is no security consideration, it does not require unlocking, so it runs more efficiently. We use it if we need security in programmingStringBuilder




 That’s it for this sharing. I hope my sharing can be helpful to you. I also welcome everyone’s support. Your likes are the biggest motivation for bloggers to update! If you have different opinions, you are welcome to actively discuss and exchange in the comment area, let us learn and make progress together! If you have relevant questions, you can also send a private message to the blogger. The comment area and private messages will be carefully checked. See you next time

Guess you like

Origin blog.csdn.net/m0_69519887/article/details/134553065