The difference between String, StringBuilder, StringBuffer in Java

1. What is it?

  • String immutable character sequence

String is a string constant. Once its object is created, the object cannot be changed. Therefore, every time the String type is changed, it is actually equivalent to generating a new String object and then pointing the pointer to the new String object. Therefore, it is best not to use String for strings that frequently change content, because each time a new object is generated, a new memory space will be opened. When there are too many unreferenced objects in the memory, the JVM GC will start to work, and the speed must be quite slow. , Have an impact on system performance.
The String class is very special. The special thing is that the JVM has done some processing specifically for it: there is a string constant pool in the JVM, which contains many String objects, and can be shared. When creating a string constant, for example, String str = "Chittyo"; will first look for the same string definition in the string constant pool, if it has already been defined, it will directly quote its definition, and there is no need to create a new one at this time Object; if it is not defined, you need to create an object, then add it to the string constant pool, and then return its reference. Since a string is an immutable class, it cannot be modified once it is created, so the string object can be shared without causing confusion in the program.

  • StringBuilder variable character sequence, high efficiency, non-thread safe

java.lang.StringBuilder is a new variable character sequence added in Java 5.0. This class provides an API compatible with StringBuffer, but does not guarantee synchronization. This class is designed to be used as a simple replacement for StringBuffer, when the string buffer is used by a single thread (this situation is very common). If possible, recommend priority use of the class, because in most implementations, it is faster than StringBuffer. The two methods are basically the same.

  • StringBuffer variable character sequence, low efficiency, thread safety

Java.lang.StringBuffer is a thread-safe variable character sequence. A string buffer similar to String. Although it contains a certain sequence of characters at any point in time, the length and content of the sequence can be changed through certain method calls. The string buffer can be safely used for multiple threads. These methods can be synchronized when necessary, so all operations on any particular instance appear to occur in serial order, which is consistent with the order of method calls made by each thread involved. Each string generator has a certain capacity. As long as the length of the character sequence contained in the string generator does not exceed this capacity, there is no need to allocate a new content buffer. If the content buffer overflows, this capacity is automatically increased.
The main operations on StringBuffer are append() and insert() methods, which can be overloaded to accept any type of data. Each method can be effective in a given data into a string, then the character string is added or inserted into a string buffer. The append() method always adds these characters to the end of the buffer; the insert() method adds characters at the specified point.

2. What is the difference?

There are two main differences: running speed and thread safety.

1. Running speed (execution speed)

The running speed: StringBuilder> StringBuffer> String.

Why is String the slowest? Because String is a string constant, and StringBuilder and StringBuffer are both string variables, that is, once the String object is created, the object cannot be changed, but the objects of the latter two are variables and can be changed.
If you don't close the code, give a chestnut:

String str = "Chitty";
System.out.println(str);
str = str + "o";
System.out.println(str);

Running this code will output "Chitty" first and then "Chittyo". It looks like the str object has been changed, but it is not. It's just an illusion.
Insert picture description here
The JVM handles these lines of code in this way (for rigor, assuming that the strings in the above code are created for the first time and cannot be found in the string constant pool), first a new memory space is created in the heap memory , Assigned to the String object str created in the first line, and assign "Chitty" to str, then in the third line, JVM creates two more memory spaces in the heap memory to store "o" and the final String object str. Therefore, the str in the first line has not actually been changed, that is, the String object mentioned earlier cannot be changed once it is created. The original str ("Chitty") in the first line and the newly created "o" in the third line will not be immediately reclaimed by the garbage collection mechanism (GC) of the JVM. The timing of the GC is when the JVM is in At some point, the execution started, so it will not be obvious that the newly opened memory space and reclaimed memory will cause the String to slow down. Strictly speaking, when a large number of String splicing operations appear, the JVM opens up too much memory space, which leads to memory shortage, and basically performs GC in real time, which will cause the speed to slow down. The operation of String objects in Java is actually a process of constantly creating new objects and reclaiming old objects in due course. This is not only a huge waste of memory space, but also slow execution speed. The objects of StringBuilder and StringBuffer are variables, which can be modified multiple times without creating new objects, that is, without creating and recycling operations, so the speed is much faster than String.

Give another example:

String str = "Chitty" + "o";
StringBuilder stringBuilder = new StringBuilder().append("Chitty").append("o");
System.out.println(str);
System.out.println(stringBuilder.toString());

The output result is also "Chittyo" and "Chittyo", but the speed of String is much faster than that of StringBuilder, this is because of the operation in line 1.

String str = "Chitty" + "o";

with

String str = "Chittyo"; 

It's exactly the same, so it will be fast. If written in the following form,

String str1 = "Chitty";
String str2 = "o";
String str = str1 + str2;

Then, the JVM will continue to create and reclaim objects to perform this operation as mentioned above. The speed will be very slow.

Because StringBuilder has a speed advantage over StringBuffer, it is recommended to use StringBuilder class in most cases. However, when the application requires thread safety, you must use the StringBuffer class. Let's look at the difference in thread safety below.

2. Thread safety

StringBuilder is thread-unsafe, while StringBuffer is thread-safe.
If a StringBuffer object is used by multiple threads in the string buffer, many methods in StringBuffer can carry the synchronized keyword, so the thread is safe. But StringBuilder methods do not have this keyword, so thread safety cannot be guaranteed, and some wrong operations may occur. Therefore, it is recommended to use StringBuilder which is faster when operating in a multi-threaded environment and using StringBuffer in a single-threaded environment.

Three, summary

  • Use String to manipulate a small amount of string data;
  • StringBuilder is used for a large number of operations in the character buffer under a single thread (recommended);
  • StringBuffer is used for a large number of operations in the character buffer under multithreading.

Four, extra meals

String strA = "Chittyo";
String strB = "Chittyo";
String strC = new String("Chittyo");
String strD = new String("Chittyo");
System.out.println(strA == strB);
System.out.println(strC == strD);

Q: What is the difference between the two ways of creating String objects?
A: First look at the print result: the fifth line is printed true; the sixth line is printed false.

Analysis: We know that eight kinds of Java basic data types (int, long, short, double , float, byte, char, boolean) by ==comparing the value of a variable, because they have no address, only the value. String is a reference data type, and ==compares the addresses of two reference variables.

strC and strD are two completely different objects from new. The addresses of the referenced variables are different, but the values ​​are equal. Analogical memory: two people just have the same name. So the sixth line is printed false.
Take a look at the process of creating a new object:

① execution String strC = new String("Chittyo");time, JVM directly create a new object and have strCpointed to the object;
② execution String strD = new String("Chittyo");time, JVM creates a new object again and have strDto point to the object;
③ so strCand strDpoint to a different object, that different addresses referenced variables.

What about strA ==strB? strA and strB are not created by new, so their address depends on the value assigned later. In Java, ordinary strings are stored in the string constant pool, and the string constant pool is currently in the heap memory (JDK 1.8, JVM moved the string constant pool to the heap memory).
Let's take a look again, the direct assignment process:

① execution String strA = "Chittyo";after, JVM string constant pool open up space for a “Chittyo”string space and let strApoint to that object.
② execution String strB = "Chittyo";time, JVM will check whether the string constant pool has been around for a content "Chittyo"space, if there is to directly strBpoint to that space, otherwise it will open in a new space to store the string.
③ so create strBtime, because the string constant pool has a string "Chittyo", so directly strBpoint to that space. Is equivalent to:String strB = strA;

Therefore, from the perspective of assignment, strA ==strB at this time is valid, and the comparison is the value in the string constant pool. (The string constant pool is in the heap memory) The
Insert picture description here
reference type points to an object, and the variable that points to the object is a reference variable. These variables are specified as a specific type when they are declared. Once the variable is declared, the type cannot be changed. Objects and arrays are all reference data types. The default value for all reference types is null. A reference variable can be used to refer to any compatible type.

Generally, for objects, when comparing whether the values ​​are equal, they are all compared by overriding the equals() method and the hashCode() method. String to compare different types of target content is the same, should be used equals()as ==a comparison reference data type and has a basic data types of different functions.

==It is used to compare basic data types to determine whether the reference points to the same block of heap memory.
equals()Used to determine whether two variables are referenced by the same object, that is, whether the contents in the heap are the same, and the return value is of Boolean type.

String str1 = new String("Chittyo");
String str2 = new String("Chittyo");
String str3 = str1;
System.out.println(str1 == str2);     //false
System.out.println(str1.equals(str2));//true
System.out.println(str1 == str3);     //true
System.out.println(str1.equals(str3); //true

Cleverly: ==Used to compare the value in the stack memory, equals()used to compare the value in the heap memory.

JVM divides memory into two types: one is stack memory and the other is heap memory.
  ① The variables of some basic data types defined in functions and reference variables (variable names) of objects are allocated in the stack memory of the function.
  ② When a variable is defined in a code block, Java allocates memory space for this variable in the stack. When the scope of the variable is exceeded, Java will automatically release the memory space allocated for the variable, and the memory space can be immediately Used for other purposes.
  ③ Heap memory is used to store objects created by new (including classes wrapped by basic types: Integer, String, Double, etc., in fact, each basic type has its packaging class) and arrays.

Guess you like

Origin blog.csdn.net/CHITTY1993/article/details/109200929