In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-11 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains the "Java string construction and splicing", the content of the article is simple and clear, easy to learn and understand, the following please follow the editor's ideas slowly in depth, together to study and learn "Java string construction and splicing" it!
2.1 Construction string
Strings are immutable in Java, whether constructed or intercepted, the result is always a new string. Take a look at constructing a string source code
Private final char value []; public String (String original) {this.value = original.value; this.hash = original.hash;}
The original value array of strings is directly assigned to the new string value by reference, that is, two strings share a char array, so this construction method has the fastest construction. The String object in Java is designed to be immutable. It means that once the program gets the string object reference, you don't have to worry about the string being modified elsewhere. Immutability means thread safety, which is explained in the third chapter.
Construct strings more often the string is constructed through an array of strings, or in some frames deserialization, using byte [] to construct strings, in which case performance can be very low. The following is the construction of a new string source code through the char [] array
Public String (char value []) {this.value = Arrays.copyOf (value, value.length);}
Arrays.copyOf will re-copy the new array as follows
Public static char [] copyOf (char [] original, int newLength) {char [] copy = new char [newLength]; System.arraycopy (original, 0, copy, 0, Math.min (original.length, newLength)); return copy;}
You can see that constructing a string from an array actually creates a new array of strings. If you don't, refer directly to the char array, and if you change the char array externally, the new string will be changed.
Char [] cs = new char [] {'axiajiaojia'}; String str = new String (cs); cs [0] ='!'
The last line of code above modifies the cs array without affecting str. Because str is actually a new array of strings
Constructing a new string from the char array is the longest method, and as we'll see later, almost every string API calls this method to construct a new string, such as subString,concat and so on. The following code verifies the performance comparison of constructing a new string from a string and using an char array to construct a string
String str= "Hello, String"; char [] chars = str.toCharArray (); [@ Benchmark] (https://my.oschina.net/u/3268003)public String string () {return new String (str);} [@ Benchmark] (https://my.oschina.net/u/3268003)public String stringByCharArray () {return new String (chars);})
The output is output according to ns/op. Since the number of nanoseconds used for each call, you can see whether it is time-consuming to construct a string through char, especially if the array is particularly long.
Benchmark Mode Score Units c.i.c.c.NewStringTest.string avgt 4.235 ns/op c.i.c.c.NewStringTest.stringByCharArray avgt 11.704 ns/op
Constructing strings through bytes is a very common situation, especially now that distributed and micro-services are popular. Strings are serialized into byte arrays on the client side and sent to you on the server side. The server side will have a deserialization to construct strings through byte.
The following test uses byte to construct a string performance test
Byte [] bs = "Hello, String" .getBytes ("UTF-8"); [@ Benchmark] (https://my.oschina.net/u/3268003)public String stringByByteArray () throws Exception {return new String (bs, "UTF-8");}
The test results show that the byte construction string is too time-consuming, especially if the string to be constructed is very long
Benchmark Mode Score Units c.i.c.c.NewStringTest.string avgt 4.649 ns/op c.i.c.c.NewStringTest.stringByByteArray avgt 82.166 ns/op c.i.c.c.NewStringTest.stringByCharArray avgt 12.138 ns/op
The string is constructed by byte array, which mainly involves the transcoding process, and StringCoding.decode transcoding is called internally.
This.value = StringCoding.decode (charsetName, bytes, offset, length)
CharsetName stands for character set, bytes is a byte array, and offset and length represent byte array
It is the Charset subclass that is actually responsible for transcoding. For example, the decode method of sun.nio.cs.UTF_8 is responsible for implementing byte transcoding. If you go deep into this class, you will find that what you see is a corner of the ice. Under the ice, this is a very expensive CPU computational transcoding work, which cannot be optimized.
In my many system performance optimization processes, I will find that constructing strings through byte data sets is always at the top of the consumption of CPU, and the system performance consumed by transcoding is worth hundreds of lines of business code. Therefore, when our system is designed to be distributed, we need to carefully design the fields that need to be transmitted and avoid using String as far as possible. For example, time can be represented by long type, and business status can be expressed by int. The following objects need to be serialized
Public class OrderResponse {/ / order date, format 'yyyy-MM-dd' private String createDate; / / order status, "0 indicates normal private String status;}
Can be improved to a better definition to reduce the serialization and deserialization burden.
Public class OrderResponse {/ / order date private long createDate; / / order status. 0 indicates normal private int status;}
With regard to serialization and deserialization of transport objects in microservices, serialization of objects will be covered again in chapters 4 and 5.
2.2 string concatenation
JDK automatically converts string concatenation using the + sign to StringBuilder, as shown in the following code:
String a = "hello"; String b = "world" String str=a+b
The virtual machine is compiled into the following code
String str = new StringBuilder () .append (a) .append (b) .toString ()
If you run JMH to test these two pieces of code, the performance is actually the same, because using + concatenation strings is a common operation, the virtual machine will do some optimization to the above two code snippets, virtual use-XX:+OptimizeStringConcat to turn on string splicing optimization (on by default). If you use the following code, although it looks similar to the code snippet above, the virtual machine does not recognize this string concatenation pattern, and the performance will degrade a lot.
StringBuilder sb = new StringBuilder (); sb.append (a); sb.append (b)
Run the StringConcatTest class with the following code
String a = "select u.idjold u.name from user u"; String b = "where u.idwritten?"; [@ Benchmark] (https://my.oschina.net/u/3268003)public String concat () {String c = axib; return c;} [@ Benchmark] (https://my.oschina.net/u/3268003)public String concatbyOptimizeBuilder () {String c = new StringBuilder () .append (a) .append (b) .toString (); return c) } @ Benchmarkpublic String concatbyBuilder () {/ / will not optimize StringBuilder sb = new StringBuilder (); sb.append (a); sb.append (b); return sb.toString ();}
The following results show that virtual machine optimization plays a role.
Benchmark Mode Score Units c.i.c.c.StringConcatTest.concat avgt 25.747 ns/op c.i.c.c.StringConcatTest.concatbyBuilder avgt 90.548 ns/op c.i.c.c.StringConcatTest.concatbyOptimizeBuilder avgt 21.904 ns/op
You can see that concatbyBuilder is the slowest because it is not optimized by JVM
JVM optimization here refers to virtual machine JIT optimization, which we will explain in Chapter 8 JIT optimization.
Readers can verify the string concatenation performance of a+b+c themselves to see if it has been optimized.
Similar to StringBuilder is StringBuffer, whose main functions inherit AbstractStringBuilder and provide thread-safe methods, such as the append method, using the synchronized keyword
@ Overridepublic synchronized StringBuffer append (String str) {/ / ignore other code super.append (str); return this;}
Almost all scenario string concatenation does not involve thread synchronization, so StringBuffer is rarely used, such as the string concatenation example above uses StringBuffer
@ Benchmark public String concatbyBuffer () {StringBuffer sb = new StringBuffer (); sb.append (a); sb.append (b); return sb.toString ();}
The output is as follows
Benchmark Mode Score Unitsc.i.c.c.StringConcatTest.concatbyBuffer avgt 111.417 ns/opc.i.c.c.StringConcatTest.concatbyBuilder avgt 94.758 ns/op
As you can see, the performance of StringBuffer stitching is not poor compared with StringBuilder, thanks to the "escape analysis" of the virtual machine, that is, when JIT turns on the escape analysis situation and lock elimination, it is possible to eliminate synchronzied-qualified locks on the object.
Escape Analysis-XX:+DoEscapeAnalysis and Lock removal-XX:+EliminateLocks, see Chapter 8 of this book for JIT optimization
The following is an example of lock elimination. The object obj is used only inside the method, so synchronized can be eliminated.
Void foo () {/ / create an object Object obj = new Object (); synchronized (obj) {doSomething ();}}
Programs should not rely on JIT optimization, and although escape analysis and lock elimination are turned on, there is no guarantee that all code will be optimized, because lock elimination is optimized during the C2 phase of JIT, and programmers should use StringBuilder regardless of thread safety.
Using StringBuilder to concatenate other types, especially numeric types, results in significant performance degradation, because numeric type conversion is internal to JDK and requires a lot of work. A simple Int type is converted to a string, which requires at least 50 lines of code. We have seen it in the first chapter and will not elaborate on it here. When you use StringBuilder to concatenate strings, concatenate numbers, you need to think about whether you need such a string.
2.10 BigDecimal
We all know that floating-point variables will lose precision when calculating. The following code
System.out.println (0.050.01), System.out.println (1.00.42)
Output: 0.060000000000000005 0.5800000000000001
You can see that the problem of loss of precision occurs when floating-point operations are performed in Java. Then if we calculate the price of goods, there will be problems. It is very likely that we have 0.06 yuan in hand, but we are unable to buy a commodity of 0.05 yuan and 0.01 yuan. Because as shown above, the sum of the two of them is 0.0600000000000005. This is undoubtedly a very serious problem, especially when the concurrency of e-commerce websites goes up, the problem will be huge. It may result in the inability to place an order or a problem with the reconciliation.
There are usually two ways to solve this problem, and it is most efficient if you can use long to represent the account balance in units. If not, you can only use the BigDecimal class to solve this type of problem.
BigDecimal a = new BigDecimal; BigDecimal b = new BigDecimal; BigDecimal ret = a.add (b); System.out.println (ret.toString ())
Using string to construct BigDecimal, the precision can not be lost. If new BigDecimal is used, the precision of the constructed BigDecimal will also be lost because of the loss of precision.
BigDecimal can guarantee the accuracy, but the calculation will have a certain performance impact. The following is the calculation of the test balance, using long to express the score, and BigDecimal to represent the performance comparison of the element.
BigDecimal a = new BigDecimal; BigDecimal b = new BigDecimal; long c = 5 CompilerControl.Mode.DONT_INLINE long d = 1 CompilerControl.Mode.DONT_INLINE benchmark CompilerControl (CompilerControl.Mode.DONT_INLINE) public long addByLong () {return (c + d);} @ Benchmark@CompilerControl (CompilerControl.Mode.DONT_INLINE) CompilerControl () {return a.add (b);}
In my machine line, the above code can be calculated accurately. Through JMH, the test results are as follows
Benchmark Mode Score Units c.i.c.c.BigDecimalTest.addByBigDecimal avgt 8.373 ns/op c.i.c.c.BigDecimalTest.addByLong avgt 2.984 ns/op Thank you for your reading. This is the content of "Construction and splicing of Java strings". After the study of this article, I believe you have a deeper understanding of the construction and splicing of Java strings, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
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.