I have summarized some of the string comprehension and usage in Java a long time ago, and finally realized some performance optimization of the string. The blog post is more about string storage. If you are interested, you can check the transfer connection.
Tested in Taobao these two daysArticleI saw an article about Java string, talked about the efficiency of stringbuilder and stringbuffer, and found that I ignored the concept of capacity. For exampleCode:
1 stringbuffer Sf = new stringbuffer (""); 2 SF. append ("leeon"); 3 system. out. println ("Length:" + SF. length (); 4 system. out. println ("Capacity:" + SF. capacity ());
The printed result is
Length: 5
Capacity: 16
We can understand the length. What is capacity?
The explanation given in the JDK source code is to store the capacity of the newly inserted character space. It can be seen that the default capacity is 16. Of course, if we rewrite the above code like the following, different results will be obtained.
1 stringbuffer Sf = new stringbuffer ("leeon"); 2 system. out. println ("Length:" + SF. length (); 3 system. out. println ("Capacity:" + SF. capacity ());
The result is
Length: 5
Capacity: 21
The reason is that when we construct SF, the value is already 5, and the new initialization capacity to be inserted is added, that is, 5 + 16. The specific implementation details are as follows:
Bytes ----------------------------------------------------------------------------------------------------------
The above is background knowledge. Next we will discuss how to optimize performance based on capacity. When you carefully read the implementation of the append method in the JDK source code, you will find that each append call requires a capacity check, because you must ensure that the stringbuffer is large enough to install the new string. Let's take a look at the Code:
When append is called, the required capacity is checked through ensurecapacityinternal. If the required capacity is insufficient, the expandcapacity is called for expansion, you can see that the resizing method is to double the current string size and then add 2. if the capacity is still insufficient, it will be expanded directly to the required size. We found that capacity expansion is a time-consuming operation. Although stringbuffer is used to process a large number of strings, it will improve performance more than string, but there is still a time-consuming part that can be optimized.
In fact, the capacity can be specified during the initialization of stringbuffer and stringbuilder. If there is a rough estimate, initialize a suitable capacity to reduce the operation of capacity expansion, the efficiency will be greatly improved. For example, in the following test code, we operate the same string for 5 million times and calculate the result.
1 stringbuilder sb = new stringbuilder (10*5000000); 2 stringbuffer Sf = new stringbuffer (10*5000000); 3 4 5 long start = system. currenttimemillis (); 6 for (INT I = 0; I <5000000; I ++) 7 {8 sb. append ("1234567890"); 9} 10 long end = system. currenttimemillis (); 11 system. out. println ("The stringbuilder run time is" + (end-Start) + "Ms"); 12 13 start = system. currenttimemillis (); 14 for (INT I = 0; I <5000000; I ++) 15 {16 SF. append ("1234567890"); 17} 18 end = system. currenttimemillis (); 19 system. out. println ("The stringbuffer run time is" + (end-Start) + "Ms ");
I did not calculate the average value of the above results. The test was conducted only in a single thread, but the data did not fluctuate much. We can see some changes. We found that when the stringbuffer is properly initialized, its performance has exceeded or even exceeded the uninitialized stringbuilder, so that we can have better security on the basis of maintaining the same efficiency as the original stringbuilder.
We can see that the initial capacity is adopted, and the performance improvement we get is higher than switching from SF to sb.
I like the conclusion of Taobao testing.
"It is more important to use the existing analogy to introduce new classes. ManyProgramWhen using stringbuffer, the member does not specify its capacity (at least I have seen it). If such a habit is introduced into the use of stringbuilder, you will only be able to achieve performance improvement of about 10% (don't forget, you have to risk multithreading); but if you use the stringbuffer of the specified capacity, you will get a performance improvement of about 45% immediately, or even about 30% faster than the stirngbuilder that does not use the specified capacity."
This issue is worth discussing later. Now we can see that it is a single thread. Can stringbuffer be optimized more in the case of multithreading?
I suddenly found myself ignoring many Java features and learning them now.