We must first remember the characteristics of the three:
- String string Constants
- StringBuffer string variable (thread safe)
- StringBuilder string variable (not thread safe)
I. Definition
The View API finds that the Charsequence interfaces are implemented by string, StringBuffer, and StringBuilder, although they are all related to strings, but their processing mechanisms are different.
- String: is a quantity that cannot be changed, that is, when it is created, it cannot be modified.
- StringBuffer: is a variable string sequence, which, like a string, holds an ordered sequence of strings (an array of char types) in memory, with the difference being that the value of the StringBuffer object is variable.
- StringBuilder: The same as the StringBuffer class, are variable character string sequences, the difference is that StringBuffer is thread-safe, StringBuilder is thread-unsafe. In terms of performance, because the operation of the string class is to produce a new string object, and StringBuilder and StringBuffer are just expansions of a character array, So the string class operates much slower than StringBuffer and StringBuilder.
Second, the use of the scene
scenarios that use the String class: You can use a string class, such as a constant declaration, and a small number of variable operations, in a scene where the string does not change frequently.
Scenarios using the StringBuffer class: frequent string operations (such as stitching, substitution, deletion, and so on), and running in a multithreaded environment, you can consider using StringBuffer, such as XML parsing, HTTP parameter parsing, and encapsulation.
Scenarios using the StringBuilder class: frequent string operations such as stitching, substitution, and deletion, and running in a single-threaded environment, you can consider using StringBuilder, such as Assembly of SQL statements, JSON encapsulation, and so on.
Third, analysis
briefly, the main performance difference between a string type and a StringBuffer type is that a string is an immutable object, so each time a change is made to the string, it is equivalent to generating a new string object and then pointing the pointer at the new A String object. So it's best not to use strings that often change the content, because each generation has an impact on system performance, especially if the JVM's GC begins to work when there is more than one object in memory, and that speed is bound to be quite slow.
If you use the StringBuffer class, the result is different, and each result operates on the StringBuffer object itself, rather than generating a new object, and then changing the object reference. So in general we recommend using StringBuffer, especially when string objects change frequently. In some special cases, string concatenation of string objects is actually interpreted by the JVM as a concatenation of the StringBuffer objects, so the speed of the string object is not slower than the StringBuffer object, especially in the following string object generation, Stri NG efficiency is far faster than StringBuffer:
String S1 = "This are only a" + "simple" + "test";
StringBuffer Sb = new StringBuilder ("This are only a"). Append ("simple"). Append ("test");
You would be surprised to find that the String S1 object was generated at a rate that was simply too fast, and at this point the StringBuffer was not at all dominant in speed. This is actually a trick of the JVM, and in the eyes of the JVM, this
is actually:
String S1 = "This is a simple test";
So of course it doesn't take too much time. But what you should be aware of here is that if your string is from another string object, the speed is not that fast, for example:
String S2 = "This are only a";
String S3 = "simple";
String S4 = "Test";
String S1 = S2 +s3 + S4;
This time the JVM will behave in the same way as it did.
Four, the Deep JVM optimization processing
is there really a performance cost, string concatenation is so common, there is no special processing optimization, the answer is yes, this optimization is compiled in the JVM. Java to bytecode.
If a Java program wants to run, it needs to go through two of times, compile time and run time. At compile time, the Java JVM (Compiler) converts Java files into bytecode. At run time, the Java Virtual Machine (JVM) runs the byte code generated at compile time. Through such two periods, Java has done what is called a compilation, run everywhere.
We experimented with the optimizations that were made at compile time, and we created code that might have a performance penalty.
public class Concatenation {public
static void Main (string[] args) {
String userName = "Andy";
String age = ";
" String job = "Developer";
String info = userName + age + job;
SYSTEM.OUT.PRINTLN (info);
}
Compile the Concatenation.java. Get Concatenation.class
Then we use JAVAP to decompile the compiled Concatenation.class file. javap-c concatenation. If you do not find the JAVAP command, consider adding the JAVAP directory to the environment variable or using the full path of JAVAP.
17:22:04-androidyue~/workspace_adt/strings/src$ javap-c concatenation Compiled from ' Concatenation.java ' public class
concatenation {public concatenation (); code:0: Aload_0 1:invokespecial #1//Method Java/lang/object. "
<init> ":() V 4:return public static void Main (java.lang.string[]);
code:0: LDC #2//String Andy 2:astore_1 3:ldc #3//String 5:astore_2
6:LDC #4//String Developer 8:astore_3 9:new #5//Class Java/lang/stringbuilder 12:dup 13:invokespecial #6//Method Java/lang/stringbuilder. " <init> ":() V 16:aload_1 17:invokevirtual #7//Method Java/lang/stringbuilder.append: (Ljava/lang/stri
ng;) Ljava/lang/stringbuilder; 20:aload_2 21:invokevirtual #7//Method Java/lang/stringbuilder.append: (ljava/lang/string;) ljava/lang/string
Builder; 24:aload_3 25:invokevirtual #7//Method java/laNg/stringbuilder.append: (ljava/lang/string;) Ljava/lang/stringbuilder;
28:invokevirtual #8//Method java/lang/stringbuilder.tostring: () ljava/lang/string;
31:astore 4 33:getstatic #9//Field Java/lang/system.out:ljava/io/printstream;
36:aload 4 38:invokevirtual #10//Method Java/io/printstream.println: (ljava/lang/string;) V 41:return
}
In which, Ldc,astore, such as Java bytecode directives, similar to the assembly instructions. The following comments are illustrated with Java-related content. We can see that there are a lot of StringBuilder, but we do not show in the Java code to call, this is JAVAJVM do optimization, when the JAVAJVM encountered string concatenation, will create a StringBuilder object, the back of the stitching, is actually the Append method that invokes the StringBuilder object. So there won't be any problems that we're worried about.
V. JVM optimization only?
now that the JVM has helped us optimize, isn't it enough to rely solely on JVM optimizations, of course not.
Let's look at some of the less optimized performance code
public void Implicitusestringbuilder (string[] values) {
String result = "";
for (int i = 0; i < values.length i + +) {result
= Values[i];
}
SYSTEM.OUT.PRINTLN (result);
}
Using Javac compilation, use JAVAP to view
public void Implicitusestringbuilder (java.lang.string[]);
code:0: LDC #11//String 2:astore_2 3:iconst_0 4:istore_3 5:iload_3 6:aload_1 7:arraylength 8:if_icmpge 11:new #5//class Java/lang/stringbuilder 14:dup 15:in Vokespecial #6//Method Java/lang/stringbuilder. " <init> ":() V 18:aload_2 19:invokevirtual #7//Method Java/lang/stringbuilder.append: (Ljava/lang/stri
ng;) Ljava/lang/stringbuilder; 22:aload_1 23:iload_3 24:aaload 25:invokevirtual #7//Method Java/lang/stringbuilder.append: (Ljava/l
ang/string;) Ljava/lang/stringbuilder;
28:invokevirtual #8//Method java/lang/stringbuilder.tostring: () ljava/lang/string; 31:astore_2 32:iinc 3, 1 35:goto 5 38:getstatic #9//Field java/lang/system.out:ljava/io/p
Rintstream; 41:aload_2 42:invokevirtual #10//Method Java/io/printstream.println: (Ljava/lang/string) V 45:return
Where 8:if_icmpge 38 and 35:goto 5 constitute a cycle. 8:IF_ICMPGE 38 means that if the integer contrast of the JVM operand stack is greater than or equal to (the opposite result of I < values.length), skip to line 38th (System.out). 35:goto 5 indicates that you are jumping directly to line 5th.
But one of the important things about this is that StringBuilder object creation occurs between loops, which means how many StringBuilder objects the loop creates, which is obviously not good. Naked Low-level code AH.
A little optimization, instant lifting force lattice.
public void Explicitusestringbuider (string[] values) {
StringBuilder result = new StringBuilder ();
for (int i = 0; i < values.length i + +) {
result.append (values[i]);
}
The corresponding compiled information
public void Explicitusestringbuider (java.lang.string[]);
Code:
0:new #5 //class Java/lang/stringbuilder
3:dup
4:invokespecial #6 //Method java/ Lang/stringbuilder. " <init> ":() V
7:astore_2
8:iconst_0
9:istore_3
10:iload_3
11:aload_1
12: Arraylength
13:if_icmpge
16:aload_2
17:aload_1
18:iload_3
19:aaload
20: Invokevirtual #7 //Method Java/lang/stringbuilder.append: (ljava/lang/string;) Ljava/lang/stringbuilder;
23:pop
24:iinc 3, 1
27:goto
30:return
As you can see from the above, 13:if_icmpge 30 and 27:goto 10 make up a loop loop, and 0:new #5位于循环之外, so you don't create StringBuilder multiple times.
In general, we need to avoid implicitly or explicitly creating StringBuilder in the loop body. So those who understand how the code compiles, how the internal execution of the people, write the code is relatively high grade.
Vi. Conclusion
In most cases stringbuffer > String
Java.lang.StringBuffer is a thread-safe variable character sequence. A string buffer similar to strings, but cannot be modified. Although it contains a particular sequence of characters at any point in time, some method calls can change the length and content of the sequence. A string buffer can be used securely in a program for multithreading. And these methods can be synchronized when necessary, so all operations on any particular instance appear to occur in a sequential sequence that is consistent with the sequence of method calls made by each thread involved.
The main operations on StringBuffer are the Append and insert methods, which can be overloaded to accept any type of data. Each method effectively converts the given data to a string, and then appends or inserts the character of the string into the string buffer. The Append method always adds these characters to the end of the buffer, and the Insert method adds the characters at the specified point.
For example, if z references a string buffer object where the current content is "start", the method call Z.append ("le") causes the string buffer to contain a "startle" (additive), while Z.insert (4, "le") changes the string buffer to include the " Starlet ".
In most cases StringBuilder > StringBuffer
Java.lang.StringBuilder A variable sequence of characters is added to Java 5.0. This class provides an API that is compatible with StringBuffer, but does not guarantee synchronization, so a single thread is used for the scenario. This class is designed as a simple replacement for stringbuffer, which is common when a string buffer is used by a single thread. If possible, it is recommended that this class be preferred, because in most implementations it is faster than StringBuffer. The use of the two methods is basically the same.