Use stringbuilder (stringbuffer) # will append replace string "+" improve performance?

Source: Internet
Author: User

I often see some forums talking about Java code optimization and talking about changing the "+" character string connection operation to stringbuilder (or stringbuffer. For the sake of simplicity, refer only to stringbuilder) in order to improve the performance of the append operation, then the string connection uses stringbuilder # append to replace "+" will actually improve the performance? If you are not busy answering questions, let's take a look at several examples. The Code is as follows:

public
class
StringConcat {    public
static void
main(String... args) {
        concat1();        concat2();        concat3();    }     public
static void
concat1() {
        String s =
"today is " +
"a good day";        System.out.println(s);    }     public
static void
concat2() {
        int
count = 2;        String tmp =
" on the desk";        String s2 =
"there are " + count +
" books " + tmp;        System.out.println(s2);    }     public
static void
concat3() {
        String s3 =
"";        for(int
i=0; i<100; i++) {            s3 = s3 + i;        }        System.out.println(s3);    }}

Next, analyze the methods of these three operation strings and decompile them using the javap command. class file: javap-C stringconcat. The command for obtaining bytecode is as follows (only concat1, concat2, and concat3 methods are extracted ):

public
static
void concat1();  Code:   0:   ldc     #5;
//String today is a good day   2:   astore_0   3:   getstatic       #6;
//Field java/lang/System.out:Ljava/io/PrintStream;   6:   aload_0   7:   invokevirtual   #7;
//Method java/io/PrintStream.println:(Ljava/lang/String;)V   10
return public
static
void concat2();  Code:   0:   iconst_2   1:   istore_0   2:   ldc     #8;
//String  on the desk   4:   astore_1   5:  
new#9;
//class java/lang/StringBuilder   8:   dup   9:   invokespecial   #10;
//Method java/lang/StringBuilder."<init>":()V   12:  ldc     #11;
//String there are   14:  invokevirtual   #12;
//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   17:  iload_0   18:  invokevirtual   #13;
//Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;   21:  ldc     #14;
//String  books   23:  invokevirtual   #12;
//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   26:  aload_1   27:  invokevirtual   #12;
//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   30:  invokevirtual   #15;
//Method java/lang/StringBuilder.toString:()Ljava/lang/String;   33:  astore_2   34:  getstatic       #6;
//Field java/lang/System.out:Ljava/io/PrintStream;   37:  aload_2   38:  invokevirtual   #7;
//Method java/io/PrintStream.println:(Ljava/lang/String;)V   41
return public
static
void concat3();  Code:   0:   ldc     #16;
//String   2:   astore_0   3:   iconst_0   4:   istore_1   5:   iload_1   6:   bipush 
100   8:   if_icmpge      
36   11
new#9;
//class java/lang/StringBuilder   14:  dup   15:  invokespecial   #10;
//Method java/lang/StringBuilder."<init>":()V   18:  aload_0   19:  invokevirtual   #12;
//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   22:  iload_1   23:  invokevirtual   #13;
//Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;   26:  invokevirtual   #15;
//Method java/lang/StringBuilder.toString:()Ljava/lang/String;   29:  astore_0   30:  iinc   
1, 1   33
goto5   36:  getstatic       #6;
//Field java/lang/System.out:Ljava/io/PrintStream;   39:  aload_0   40:  invokevirtual   #7;
//Method java/io/PrintStream.println:(Ljava/lang/String;)V

To analyze the bytecode Meanings of the three methods.

In concat1, there is a link between two nominal values (string constants), from the concat1 byte code 0th (0: LDC #5; // string today is a good day) as you can see, this method loads "string today is a good day" directly from the constant pool, that is, string S = "today is" + "A Good Day "; after compilation, this statement has become a string, which is equivalent to string S = "string today is a good day". No connection operation is required during running, therefore, the use of stringbuilder makes no sense for the string literal value connection.

In concat2, variables are involved in the string connection. It can be seen from the decompiled bytecode that the append operation of stringbuilder has been converted during compilation,

String s2 =
"there are " + count +
" books " + tmp;

After the statement is compiled, it is equivalent to the command between [5, 30 ):

String s2 =
new StringBuilder().append("there are ").append(count).append(" books").append(tmp).toString();

It can be seen that new stringbuilder () is explicitly used in such a string connection code (). append does not improve performance because the string "+" operator has been converted to new stringbuilder () during compilation (). append. Of course, stringbuilder can pass in an int parameter as its initial capacity, which cannot be achieved in the generated code, but can only be controlled by the program.

Finally, let's take a look at concat3, use a string connection in the for loop, and finally use the connected string outside the for loop. [] In bytecode is a circular body, which is easy to find. The new stringbuilder operation is performed in the circular body. The meaning of the Code represented by the bytecode is as follows:

String s3 =
"";for(int
i=0; i<100; i++) {    s3 =
new StringBuilder().append(s3).append(i).toString();}

In this case, the optimization of the compiler is not as intended. The optimization code we want is as follows:

String s3 =
"";StringBuilder tmp =
new StringBuilder();tmp.append(s3);for(int
i=0; i<100; i++) {    tmp.append(i);}s3 = tmp.toString();

This is a bit complicated for the compiler, and we need to do it manually.

Based on the analysis of the three methods, it is found that using stringbuilder (stringbuffer) # append to replace the string "+" does it bring about performance improvement and is not static. It is also different under different conditions, the string literal value connection has been established during compilation. Normal string connections do not need to be explicitly connected using new stringbuilder (). append to increase efficiency. The compiler has already done this unless it can provide an effective initial capacity during explicit use. In this sense, I personally think that the "+" of string can be considered as a syntactic sugar of stringbuilder # append. However, if the string connection in a loop such as concat3 is shown, we need to use stringbuilder explicitly. There was no stringbuilder class in jdk1.4, and the optimization code generated by the compiler uses stringbuffer.

The stringbuidler # append generated by the string connection operation compiler must be operated by a single thread, so there will be no thread security issues.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.