In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
Java string splicing efficiency analysis and how to practice, I believe that many inexperienced people do not know what to do, so this paper summarizes the causes of the problem and solutions, through this article I hope you can solve this problem.
There are many ways to connect a string to java, such as the + operator and the StringBuilder.append method. What are the advantages and disadvantages of each of these methods (you can properly explain the implementation details of each way)?
According to the principle of efficiency, what is the practice of string concatenation in java?
What other practices are there when it comes to string processing?
Don't talk too much nonsense, start directly, the environment is as follows:
JDK version: 1.8.0 / 65
CPU: i7 4790
Memory: 16GB
Direct use + splicing
Look at the following code:
@ Test public void test () {String str1 = "abc"; String str2 = "def"; logger.debug (str1 + str2);}
In the above code, we use the plus sign to concatenate four strings, the advantage of this string concatenation is obvious: the code is simple and intuitive, but compared to StringBuilder and StringBuffer in most cases are lower than the latter, here is most of the cases, we use the javap tool to decompile the bytecode generated by the above code to see what the compiler has done to this code.
Public void test (); Code: 0: ldc # 5 / / String abc 2: astore_1 3: ldc # 6 / / String def 5: astore_2 6: aload_0 7: getfield # 4 / / Field logger:Lorg/slf4j/Logger 10: new # 7 / / class java/lang/StringBuilder 13: dup 14: invokespecial # 8 / / Method java/lang/StringBuilder. "": () V 17: aload_1 18: invokevirtual # 9 / / Method java/lang/StringBuilder.append: (Ljava/lang/String;) Ljava/lang/StringBuilder 21: aload_2 22: invokevirtual # 9 / / Method java/lang/StringBuilder.append: (Ljava/lang/String;) Ljava/lang/StringBuilder; 25: invokevirtual # 10 / / Method java/lang/StringBuilder.toString: () Ljava/lang/String; 28: invokeinterface # 11, 2 / / InterfaceMethod org/slf4j/Logger.debug: (Ljava/lang/String;) V 33: return
From the result of decompilation, actually using the + operator to concatenate the string, the compiler will optimize the code to use the StringBuilder class during the compilation phase, and call the append method for string concatenation, and * call the toString method, so it seems that in general, you can actually use + directly, anyway, the compiler will help me optimize to use StringBuilder?
StringBuilder source code analysis
The answer is, of course, no, because of what is done inside the class StringBuilder.
Let's take a look at the constructor of the StringBuilder class
Public StringBuilder () {super (16);} public StringBuilder (int capacity) {super (capacity);} public StringBuilder (String str) {super (str.length () + 16); append (str);} public StringBuilder (CharSequence seq) {this (seq.length () + 16); append (seq);}
StringBuilder provides four default constructors and three other overloaded versions in addition to the no-parameter constructor. Internally, the super (int capacity) constructor of the parent class is called, and its parent class is AbstractStringBuilder, which is constructed as follows:
AbstractStringBuilder (int capacity) {value = new char [capacity];}
You can see that the char array is actually used internally by StringBuilder to store data (as are String and StringBuffer), where the value of capacity specifies the size of the array. Combined with StringBuilder's no-argument constructor, you can see that the default size is 16 characters.
In other words, if the total length of the string to be stitched is not less than 16 characters, then direct stitching is not much different from writing StringBuilder manually, but our own construction of StringBuilder class can specify the size of the array to avoid allocating too much memory.
Now let's take a look at what is done inside the StringBuilder.append method:
@ Override public StringBuilder append (String str) {super.append (str); return this;}
The append method of the parent class that is called directly:
Public AbstractStringBuilder append (String str) {if (str = = null) return appendNull (); int len = str.length (); ensureCapacityInternal (count + len); str.getChars (0, len, value, count); count + = len; return this;}
The ensureCapacityInternal method is called inside this method. When the total size of the concatenated string is larger than the size of the internal array value, it must be expanded before it can be concatenated. The code for expansion is as follows:
Void expandCapacity (int minimumCapacity) {int newCapacity = value.length * 2 + 2; if (newCapacity-minimumCapacity < 0) newCapacity = minimumCapacity; if (newCapacity < 0) {if (minimumCapacity < 0) / / overflow throw new OutOfMemoryError (); newCapacity = Integer.MAX_VALUE;} value = Arrays.copyOf (value, newCapacity);}
StringBuilder increases the capacity to twice the current capacity + 2 when expanding, which is terrible. If the capacity is not specified at the time of construction, it is likely to waste a lot of memory space after expansion. Secondly, after the expansion, the Arrays.copyOf method is called, which copies the data before the expansion to the space after the expansion. The reason for this is that the char array is used inside StringBuilder to store the data, and the array of java is not scalable, so it can only re-apply for a piece of memory space and copy the existing data to the new space. Here it finally calls the System.arraycopy method to copy, which is a native method. The underlying layer manipulates memory directly, so it takes more blocks than we use loops to copy, even so, the impact of a large number of requests for memory space and copying data cannot be ignored.
Compare using + stitching and using StringBuilder
@ Test public void test () {String str = ""; for (int I = 0; I < 10000; iTunes +) {str + = "asjdkla";}}
The above code is optimized to be equivalent to:
@ Test public void test () {String str = null; for (int I = 0; I < 10000; iTunes +) {str = new StringBuilder () .append (str) .append ("asjdkla") .toString ();}}
You can see at a glance that too many StringBuilder objects have been created, and the str gets bigger and bigger after each loop, resulting in more and more memory space for each application, and when the str length is greater than 16:00, scale up twice each time! In fact, when the toString method creates the String object, it calls the Arrays.copyOfRange method to copy the data, which is equivalent to expanding the capacity twice and copying the data three times for each execution, which is quite expensive.
Public void test () {StringBuilder sb = new StringBuilder ("asjdkla" .length () * 10000); for (int I = 0; I < 10000; iTunes +) {sb.append ("asjdkla");} String str = sb.toString ();}
The execution time of this code is 0ms (less than 1ms) and 1ms on my machine, while the above code is about 380ms! The gap in efficiency is quite obvious.
In the same code above, when the number of loops is adjusted to 1000000, on my machine, it takes about 20ms when a specified capacity is specified, and about 29ms when a capacity is not specified. Although this gap is greatly improved from using the + operator directly (and the number of loops is increased by 100 times), it still triggers multiple expansion and replication.
Changing the above code to use StringBuffer, on my machine, takes about 33ms, because StringBuffer adds the synchronized keyword to most methods to ensure thread safety, and the execution efficiency is reduced to some extent.
Use String.concat stitching
Now look at this code:
@ Test public void test () {String str = ""; for (int I = 0; I < 10000; iTunes +) {str.concat ("asjdkla");}}
This code uses the String.concat method, and on my machine, the execution time is about 130ms, which is much better than direct addition, but it seems useless compared to using StringBuilder. In fact, it is not. In many cases, we only need to concatenate two strings instead of concatenating multiple strings, so using the String.concat method is simpler and more efficient than StringBuilder.
Public String concat (String str) {int otherLen = str.length (); if (otherLen = = 0) {return this;} int len = value.length; char buf [] = Arrays.copyOf (value, len + otherLen); str.getChars (buf, len); return new String (buf, true);}
The above is the source code of String.concat. In this method, Arrays.copyOf is called once, and len + otherLen is specified, which is equivalent to allocating memory space and copying data from str1 and str2 respectively. If you use StringBuilder and specify capacity, it is equivalent to allocating memory space and copying data from str1 and str2 respectively. Because the toString method is called, the data is copied again.
Conclusion
Now, according to the above analysis and test, we can know:
Do not directly use + concatenation in string concatenation in Java.
When using StringBuilder or StringBuffer, estimate the capacity as accurately as possible and specify it at construction time to avoid memory waste and frequent expansion and replication.
Use StringBuilder when there are no thread safety issues, otherwise use StringBuffer.
Concatenation of two strings calls String.concat performance directly.
Other practices about String
When using equals, always write the variables that can be determined not to be empty on the left, such as using ".equals (str) to determine the empty string to avoid null pointer exceptions.
The second point is used to crowd out the dots. Using str! = null & & str.length ()! = 0 to determine an empty string is more efficient than the * * point.
When you need to convert other objects to string objects, use String.valueOf (obj) instead of calling the obj.toString () method directly, because the former already detects null values and does not throw null pointer exceptions.
Use the String.format () method to format the output of the string.
In JDK 7 and above, strings can be used in switch structures, so for more comparisons, use switch instead of if-else.
That's all I can think of for the time being. Please help me to supplement it.
After reading the above, have you mastered the efficiency analysis of Java string concatenation and how to practice it? If you want to learn more skills or want to know more about it, you are welcome to follow the industry information channel, thank you for reading!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.