JAVA中字串的split方法有兩個陷阱需要注意
JAVA中字串的split方法有兩個陷阱需要注意
在開發過程中,我們會碰到一種場景,需要對字串進行分割,從而得到更具體的資訊。
比如下面這個字串:
String str = "123455#JAVA程式設計思想#這是一本JAVA聖經級別的書籍!";
該字串包含書籍ID、書籍名稱以及簡介,三條資訊用#
號連線在一起。
想要得到這三條資訊,我們通常使用split
方法:
String[] strArray = str.split("#");
for (int i = 0; i < strArray.length; i++) {
System.out.println(strArray[0]);// 書籍ID
System.out.println(strArray[1]);// 書籍名稱
System.out.println(strArray[2]);// 簡介
}
split
使用很簡單,但一不小心,很容易掉進兩個陷阱:
split的引數是正則表示式,不是字串物件
當大家看到str.split("#")
時,很容易誤解#
是一個字串物件,實際上JDK中 split
方法定義的是正則表示式。
所以當要分割的字串是正則表示式中的特殊符號時,執行split
方法就不會得到預期的結果。
比如分隔符由#
變為 |
:
String str = "123455|JAVA程式設計思想|這是一本JAVA聖經級別的書籍!";
String[] strArray = str.split("|");
for (int i = 0; i < strArray.length; i++) {
System.out.println(i + " >> " + strArray[i]);
}
執行結果是:
0 >> 1
1 >> 2
2 >> 3
3 >> 4
4 >> 5
5 >> 5
6 >> |
7 >> J
8 >> A
9 >> V
10 >> A
11 >> 編
12 >> 程
13 >> 思
14 >> 想
15 >> |
16 >> 這
17 >> 是
18 >> 一
19 >> 本
20 >> J
21 >> A
22 >> V
23 >> A
24 >> 聖
25 >> 經
26 >> 級
27 >> 別
28 >> 的
29 >> 書
30 >> 籍
31 >> !
要解決這個問題,有兩種方法:
1、對特殊字元做轉義
正則表示式中轉義是\
,所以split的引數應該是\|
,然而\
在JAVA中也是轉義字元,即也是特殊字元,也需要轉移,所以最終split的引數是\\|
。
修改後的程式碼就是:
String str = "123455|JAVA程式設計思想|這是一本JAVA聖經級別的書籍!";
String[] strArray = str.split("\\|");
for (int i = 0; i < strArray.length; i++) {
System.out.println(i + " >> " + strArray[i]);
}
2、將特殊字元放在中括號中
正則表示式中,中括號是用來定義匹配的字元範圍。
修改後的程式碼是:
String str = "123455|JAVA程式設計思想|這是一本JAVA聖經級別的書籍!";
String[] strArray = str.split("[|]");
for (int i = 0; i < strArray.length; i++) {
System.out.println(i + " >> " + strArray[i]);
}
使用split方法時,有的特殊字元需要注意,那哪些字元需要特別關注呢?
正則表示式中有11個特殊字元:^
、$
、|
、.
、*
、+
、?
、()
、{}
、\
、/
除了/
之外,直接用其他特殊字元分割字串,都不會得到預期的結果。
甚至在使用*
、+
、?
、{}
作為分割字串時,編譯就報錯,強制我們去做轉義。
為了保證split分割的結果是正確的,也為了減少記憶特殊字串的麻煩,我建議大家在使用split時,就將分割字串放在中括號中。即使用第二種方式:
String[] strArray = str.split("[|]");
split分割後的陣列長度可能小於預期的長度
對字串進行分割後,我們可能會將這些資訊賦值給一個物件,比如:
String str = "123455#JAVA程式設計思想#這是一本JAVA聖經級別的書籍!";
String[] strArray = str.split("[#]");
Book book = new Book();
book.setId(strArray[0]);
book.setName(strArray[1]);
book.setDesc(strArray[2]);
一般情況下這是沒有問題的,但是如果分割的字串最後沒有書籍簡介,就會出問題:
String str = "123455#JAVA程式設計思想#";
String[] strArray = str.split("[#]");
for (int i = 0; i < strArray.length; i++) {
System.out.println(i + " >> " + strArray[i]);
}
執行程式碼的結果是:
0 >> 123455
1 >> JAVA程式設計思想
也就是分割後的陣列長度是2,而我們預期的長度是3,所以執行book.setDesc(strArray[2])
程式碼就會報錯。
如果想讓上面的字串分割後的陣列長度為3,應該怎麼處理?split方法中提供了第二個引數:
String str = "123455#JAVA程式設計思想#";
String[] strArray = str.split("[#]", 3);
for (int i = 0; i < strArray.length; i++) {
System.out.println(i + " >> " + strArray[i]);
}
執行程式碼的結果是:
0 >> 123455
1 >> JAVA程式設計思想
2 >>
檢視JDK的原始碼,可以發現split只傳一個引數時,實際上第二個引數預設傳的是0。
當第二個引數limit
的值大於0時,表示將字串分割為幾段(也就是陣列長度),但這個長度也不能大於字串中分割字串的個數+1。
String str = "a##b#";
String[] arr1 = str.split("[#]", 2);
/**
分割後的陣列為:
arr1[0] = "a";
arr1[1] = "#b#";
*/
String[] arr2 = str.split("[#]", 3);
/**
分割後的陣列為:
arr2[0] = "a";
arr2[1] = "";
arr2[2] = "b#";
*/
String[] arr3 = str.split("[#]", 4);
/**
分割後的陣列為:
arr3[0] = "a";
arr3[1] = "";
arr3[2] = "b";
arr3[3] = "";
*/
String[] arr4 = str.split("[#]", 5);
/**
字串中的#有3個,最多能分割成長度為4的陣列,所以第二個引數傳5時,結果和傳4是一樣的:
arr4[0] = "a";
arr4[1] = "";
arr4[2] = "b";
arr4[3] = "";
*/
當第二個引數limit
的值小於0時,結果就有些出人意料了,得到的陣列是完全按照指定字元分割的。
String str = "a##b#";
String[] arr1 = str.split("[#]", -1);
/**
分割後的陣列為:
arr1[0] = "a";
arr1[1] = "";
arr1[2] = "b";
arr1[3] = "";
*/
總結
1、在使用split對字串進行分割時,將分隔符放在中括號中。str.split("[|]")
2、當要通過陣列遊標獲取分割後的資訊時,split第二個引數傳入一個負值。str.split('[|]', -1)
注意到這兩點,你在使用split方法時就絕對不會出錯啦!
看到這裡,你是否應該馬上搜索程式碼,看看split的使用都正確了?如果沒有,立即改正吧!
ps:
如果文章對你有幫助,請關注我的公眾號吧!