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:

PublicClassStringConcat {PublicStaticVoidMain (String... args) {concat1 (); concat2 (); concat3 ();}PublicStaticVoidConcat1 () {String s = "today is" + "a good day"; System. out. println (s );}PublicStaticVoidConcat2 (){IntCount = 2; String tmp = "on the desk"; String s2 = "there are" + count + "books" + tmp; System. out. println (s2 );}PublicStaticVoidConcat3 () {String s3 = "";For(IntI = 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 ):

PublicStaticVoidConcat1 (); 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 PublicStaticVoidConcat2 (); 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 ." ":() 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 VoidConcat3 (); 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 ." ":() 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 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 =NewStringBuilder (). 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(IntI = 0; I <100; I ++) {s3 =NewStringBuilder (). 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 =NewStringBuilder (); tmp. append (s3 );For(IntI = 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.

Related Article

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.