Detailed usage of String class in Java

Keywords: Java

1, Create string

There are three ways to create strings:

// Mode 1
String str = "Hello Bit";
// Mode II
String str2 = new String("Hello Bit");
// Mode III
char[] array = {'a', 'b', 'c'};
String str3 = new String(array);

We are very familiar with the first and second methods of creating strings. As for why the third method can change a character array into a String, we can press and hold the ctrl key and click into the String of the incoming character array to see its original code. We can find that the method used at this time is to copy the array and change all the characters of the character array into String form.

2, Conversion of characters, bytes and strings

1. Conversion between character and string

Because a String is equivalent to a collection of characters, to convert a character into a String, you need to call the String construction method and pass in a character array. For example:

char[] val = {'a','b','c'};
String str = new String(val);
System.out.println(str);

Of course, we can also choose from which subscript the character array starts to which subscript ends to convert the characters into the form of a string.

For example:

char[] val = {'a','b','c','d','e'};
String str1 = new String(val,0,3);
System.out.println(str1);
//The print result is abc
System.out.println("=========");
String str2 = new String(val,1,3);
System.out.println(str2);
//The print result is bcd

Because a string is a collection of characters, it can be converted to a character or an array of characters. For example, 0 and 1 in parentheses are offset, and the offset starts from 0. Therefore, take 3 characters back from the position where the offset is 0 to form a string.

If the string is to be converted to a single character, the code is as follows:

String str = "abc";
System.out.println(str.charAt(1));
//The print result is b

If the string is to be converted to a character array, the code is as follows:

char[] val = str.toCharArray();
System.out.println(Arrays.toString(val));
//Print results: [a, b, c]

2. Conversion between byte and string

To convert a byte to a string in Java, you need to convert a byte array to a string.

Convert byte array to string:

byte[] bytes = {97,98,99,100};
String str1 = new String(bytes,0,3);
System.out.println(str1);
//The print result is abc
System.out.println("========");
String str2 = new String(bytes,1,3);
System.out.println(str2);
The print result is bcd

Convert string to byte array:

String str1 = "abc";
byte[] bytes1 = str1.getBytes();
System.out.println(Arrays.toString(bytes1));
The print result is:[97, 98, 99]
//

3, String comparison

Many beginners will think that "= =" is compared with equals in the same way. In fact, there is a big difference.
For two strings, use "= =" to compare the references of variables. The equals method of String compares the contents of two strings. But here's another question: why is every String constant defined by a reference? This involves the String constant pool.

1. String constant pool

You may still be unfamiliar with the concept of "pool". Such as data connection pool, thread pool, etc. What do these pools do? It is used to improve storage efficiency. As the name suggests, a string constant pool is used to store string constants. The string constant pool specifies that as long as there is a string constant, the same string will no longer be stored. Starting from JDK 1.8, the string constant pool is in the heap. It is essentially a hash table (StringTable) is an array. The storage string constant is stored according to a mapping relationship, which requires the design of a hash function. (because the string constant pool is about the JVM, we need to look at its original code to really understand how the string constant pool operates. If we don't study its principle here, it won't affect us to judge whether the references are the same).

When a String constant is stored in the String constant pool, a node will be generated at a location calculated according to the hash function. The node is composed of the hash value, the address of the String node and the address of the next node at the location where the array is stored (this can be really understood in the original code of the JVM). Each String node is composed of a character array value and a hash value hash (0 by default) (as shown in the figure below). You can find these two variables by clicking String to see its original code. At this time, observing that the value array is modified by final indicates that the characters in the array cannot be changed, which is why the String is a constant, and the String will be converted into character form and stored in the character array.

Let's take a simple example to understand the memory layout of the string constant pool.
The code is as follows:
Code 1:

String str1 = "hello";
String str2 = "hello";
System.out.println(str1==str2);
//The print result is true

The memory layout is as follows:

Code 2:

String str1 = "hello";
String str2 = new String("hello");
System.out.println(str1==str2);
//The print result is false


Manual pool entry:
We know from the above figure that the running result in code 2 is false, because str2 points to the String object generated by new String, not the address of the String object storing "hello". What would happen if it were written as the following code?

String str1 = "hello";
String str2 = new String("hello").intern();
System.out.println(str1==str2);
//The running result is true

Why is the final result true? At this time, the intern method in the String class is called, which is called manual pooling. It can no longer point str2 to the String object from new, but to the String object with the "hello" character array stored in the String constant pool.

Code 3:

String str1 = "hello";
String str2 = "he"+"llo";
System.out.println(str1==str2);
//The print result is true

This code is about string splicing. In fact, "he" and "llo" have been compiled as "hello" at compile time. If you want to see what string str2 is at compile time, click the Build option and click the Build Project option to compile (Figure 1). Under the path of such files (including. Class files) (Figure 2 + Figure 3), hold down the shift key and right-click the powershell window, enter the decompile instruction javap -c class name, and you can see whether str2 is a spliced hello at compile time.

Figure 1:

Figure 2: right click the window of this class

Figure 3: go back to the previous folder, click out - > production - > the name of the folder where the bytecode file is located - > hold down shift, click the right mouse button and click into the powershell window - > enter the javap -c class name

Code 4:

String str1 = "11";
String str2 = new String("1")+new String("1");
System.out.println(str1==str2);
//The running result is false

String splicing will produce a StringBuffer type. Calling toString method through StringBuffer will also be transformed into string class. At this time, after splicing, the string "11" will be stored in value, but will not be stored in the string constant pool.

Through decompilation, we can see that StringBuffer is generated, and StringBuffer calls toString method to generate an object storage "11" of String class. It can be fully understood from Figure 1 and Figure 2.

Figure 1:

Figure 2:

Figure 3:

2. String content comparison

For string comparison, we cannot use "= =" directly, but there are three methods to compare strings in different ways.

Compare String contents: directly call the equals method of String class and compare the String in parentheses.
Compare String contents (regardless of case): call the equalsIgnoreCase method of the String class.

String str1 = "hello" ; 
String str2 = "Hello" ; 
System.out.println(str1.equals(str2)); // false 
System.out.println(str1.equalsIgnoreCase(str2)); // true

Compare the size in the String: call the compareTo method in the String class. Originally, there is no compareTo method in the String class, but the String class implements the Comparable interface and rewrites the compareTo method.

It is compared character by character. If str1 is greater than str2, the value of str1 minus str2 is returned. For example:

Code 1:

String str1 = "abc";
String str2 = "bcd";
System.out.println(str1.compareTo(str2));
//The operation result is: - 1

Because the ASCII value of b is 1 greater than that of a, it returns - 1 directly. (if the characters are different, return their ASCII code difference)

Code 2:

String str1 = "bcdef";
String str2 = "bcd";
System.out.println(str1.compareTo(str2));
//The operation result is 2

Because the character value of str2 is the same as that of str1 before the end of str2 comparison. So the final result is the length of str1 minus the length of str2.

The following is the implementation of the compareTo method of the String class.

4, String lookup

1. Judge whether a substring exists in the main String: call the contains method of String class, and the return value is boolean.

String str = "abbabcacc";
boolean flg = str.contains("abc");
System.out.println(flg);
//The print result is true

2. Find a substring from the beginning and return the index position from the first substring. If not, return - 1. You can also pass in an index to indicate where to start searching, and call the indexOf method in the String class.

String str = "abbabcacc";
int index = str.indexOf("abc");
System.out.println(index);
//The print result is 3

3. Search from the end to check whether there are incoming substrings in the main String. If there are, the index value is returned, and if not, the - 1 is returned. Call lastIndexOf of the String class, and you can also pass in the index to represent which index value to find from the tail to the head. Call lastIndexOf of String class
Code 1:

String str = "abbabcacc";
int index = str.lastIndexOf("ac");
System.out.println(index);
//The print result is 6

When the substring we are looking for is just "cut off", it will still get the following characters and return the index value at the beginning of the substring, but the index value of the following characters cannot be obtained.

Code 2:

String str = "abbabcacc";
int index = str.lastIndexOf("ac",6);
System.out.println(index);
//The print result is 6

4. Judge whether a String starts with the specified substring, and call the startsWith method in the String class. You can also pass in the index value description to judge whether it starts with the specified substring from the specified position.

String str = "abbabcacc";
boolean flg = str.startsWith("abb");
System.out.println(flg);
//The print result is true
String str = "abbabcacc";
boolean flg = str.startsWith("abb",3);
System.out.println(flg);
//The print result is false

5. Judge whether a String ends with a specified substring. Call the endsWith method in the String class.

String str = "abbabcacc";
boolean flg = str.endsWith("acc");
System.out.println(flg);
//The print result is true

5, String substitution

1. Replace all specified contents in the String. Call the repalceAll method in the String class.

String str = "helloworld" ; 
System.out.println(str.replaceAll("l", "_"));
//The print result is he__owor_d

You can also choose to replace the first content in the String. Call the repalceFirst method in the String class.

System.out.println(str.replaceFirst("l", "_"));
//The print result is he_loworld

Since the string is an immutable object, the replacement does not modify the current string, but produces a new string.

6, String splitting

The specified String can be divided into several groups based on the main String, which is equal to several String arrays. Therefore, the contents of the split array can be traversed through the foreach loop. Call the split method of the String class.

String str = "hello world hello bit" ; 
String[] result = str.split(" ") ; // Split by space
for(String s: result) { 
 System.out.println(s); 
}
//The print result is
hello
world
hello
bit

The split method can also pass in a limit parameter, which means that it can be divided into several arrays at most after splitting. If the number of arrays after splitting is less than the limit value, it will be split according to the number of arrays originally split. Otherwise, the number of arrays cannot exceed the limit value

String str = "hello world hello bit" ; 
String[] result = str.split(" ",2) ; 
for(String s: result) { 
 System.out.println(s); 
}
//The print result is
hello
world hello bit

Of course, string splitting can be nested, that is, it can be split into two parts first, and then split according to another string.

String str = "name=zhangsan&age=18";
String[] strings = str.split("&");
for (String s:strings) {
 String[] ss = s.split("=");
 for (String s1:ss) {
   System.out.println(s1);
 }
}
//The print result is
name
zhangsan
age
18

There are several special cases for string splitting. When the character to be split is an escape character, two more slashes need to be passed in the specified string. For example:

String str = "192.168.1.1";
String[] strings = str.split("\\.");
for (String s:strings) {
     System.out.println(s);
}
//The print result is
192
168
1
1

Therefore, it should be noted that the characters "|", "*", "+" must be preceded by the escape character "\ \".

For string splitting, you can also split according to multiple specified strings, which are separated by '|'.

String str = "Java30 12&21#hello";
String[] strings = str.split(" |&|#");
for (String s:strings) {
     System.out.println(s);
}
The print result is
Java30
12
21
hello

7, String interception

For the interception of a String, an index value is passed in to represent which index to intercept from. The two index values passed in represent the intercepted range. Call the substring method in the String class. For example:

String str = "helloworld" ;
System.out.println(str.substring(5));
System.out.println(str.substring(0, 5));
//The print result is
world
hello

be careful:

  1. Index starts at 0
  2. Pay attention to the writing method of the front closed and back open interval. substring(0, 5) indicates a character containing subscript 0, but not subscript 5

For the above string operation method, we can check its original code to better understand how the method operates.

8, Other common methods in String class

1. trim method of string class. This method is used to remove the left and right spaces in the string, and the spaces in the middle of the string will not be removed.
code:

String str = "  abc  def  ";
String s = str.trim();
System.out.println(s);
//The print result is
abc  def

2. toUpperCase and toLowerCase methods in string class. toUpperCase is used to convert lowercase letters into uppercase letters in a string, not letters. The toLowerCase method is used to convert the uppercase letters in the string into writing letters, not letters, and is not processed.

String str = " hello%$$%@#$% world hahaha "; 
System.out.println(str.toUpperCase()); 
System.out.println(str.toLowerCase());
The print result is:
HELLO%$$%@#$% WORLD hahaha 
hello%$$%@#$% world hahaha 

3. concat method in string class. This method is used to connect strings, which is equivalent to splicing in strings, but the connected strings will not be put into the string constant pool. It will not be demonstrated here.

4. The length method in the String class is used to find the length of the String. Unlike the array, the length in the array is the attribute of the array, and the length in the String is a method.
code:

String str = "abcd";
System.out.println(str.length());
//The print result is 4

5. isEmpty method in string class is used to judge whether the string is empty.
code:

System.out.println("hello".isEmpty());//false
System.out.println("".isEmpty());//true
System.out.println(new String().isEmpty());//true

9, StringBuffer and StringBuilder

After understanding the above String constant pool, we know that String is constant and immutable. When splicing, Java will optimize the splicing of String class objects to the splicing of StringBuffer during compilation (no new objects will be generated) Therefore, there are StringBuffer and StringBuilder in Java to process strings, and when they are spliced, they will not produce new objects, but spliced on the basis of the original String. Later, we will discuss the difference between StringBuilder and StringBuffer.
There is an append method in StringBuilder that can splice strings on the original basis. For example, when we have such code:

String str = "abc";
for (int i = 0; i < 10; i++) {
     str+=i;
}
System.out.println(str);
//Print results:
abc0123456789

Many temporary variables will be generated in the constant pool, for example, abc0 will be generated in the string constant pool, abc01 will be generated in the string constant pool, etc. if we use the append method of StringBuilder, it can be written as (the final results of the two methods are the same, except that temporary variables will not be generated in the string constant pool during StringBuilder processing):

StringBuilder stringBuilder = new StringBuilder("abc");
for (int i = 0; i < 10; i++) {
     stringBuilder.append(i);
}
System.out.println(stringBuilder);
//Print results:
abc0123456789

The reason why the StringBuilder type can be printed during printing is that the toString method of the parent class is overridden in StringBuilder, which can convert the StringBuilder type to String type for printing.

The append method can also be used in parallel. The code is as follows:

public static void main(String[] args) { 
StringBuffer sb = new StringBuffer(); 
sb.append("Hello").append("World"); 
fun(sb); 
System.out.println(sb); 
}
//The print result is
HelloWorld

Therefore:
String becomes StringBuffer: use the construction method or append() method of StringBuffer.
Change StringBuffer to String: call toString() method.

1. The difference between StringBuilder and StringBuffer

The methods in StringBuilder and StringBuffer are roughly the same. The main difference between them is that StringBuilder is mainly used for single threads, while StringBuffer is mainly used for multi threads. Click into the StringBuffer class and press ctrl+7 to select the append method. If you see the synchronized English as shown in the figure, it means that it is used by multiple threads, but not in the StringBuilder class.

Conclusion:

  • The contents of String cannot be modified. The contents of StringBuffer and StringBuilder can be modified
  • Most of the functions of StringBuffer and StringBuilder are similar
  • StringBuffer adopts synchronous processing, which belongs to thread safe operation; The StringBuilder does not adopt synchronous processing, which belongs to thread unsafe operation

2. Common methods of StringBuilder and StringBuffer

The methods commonly used by StringBuilder and StringBuffer are generally not available in String classes, such as append method, delete method, reserve method, insert method, etc.

reverse method:

StringBuffer sb = new StringBuffer("helloworld"); 
System.out.println(sb.reverse());
//The print result is
dlrowolleh

delete method:

StringBuffer sb = new StringBuffer("helloworld"); 
System.out.println(sb.delete(5, 10));
//The print result is
hello

insert method:

StringBuffer sb = new StringBuffer("helloworld"); 
System.out.println(sb.delete(5, 10).insert(0, "Hello"));
//The print result is:
Hello hello

10, Understanding of string references

Many people think that if you pass a reference to a function and point to another object, you can solve "all problems". In fact, it is not. The following example can illustrate the problem.
code:

    public static void func(String str1,char[] chars) {
    str1="hello";
    chars[0]='g';
    }
    public static void main(String[] args) {
        String str = "abcd";
        char[] chars = {'h','e','l','l','o'};
        func(str,chars);
        System.out.println(str);
        System.out.println(Arrays.toString(chars));
    }
    //The print result is abcd
                [g, e, l, l, o]

As a result, why doesn't str point to hello and char change from the original hello to gello? After learning the string constant pool, we learned that the string constant pool can only store one string constant with the same content. Therefore, str1 in the passed func function is a formal parameter. str1 points to the new object "hello", but str in the main function still points to abcd. chars is really based on the original array. There is no problem that the character of 0 subscript is changed to 'g', and the final printed result is [g, e, l, l, o]. The diagram is as follows:

Posted by gregtel on Sat, 20 Nov 2021 22:41:16 -0800