咦,拆分個字符串都這麼講究
摘要:String [] parts = twopart.split("沉默王二.一枚有趣的程序員")。也就意味着,我們拆分字符串有了新的選擇,可以不使用 String 類的 split() 方法了。
提到拆分字符串,我猜你十有八九會撂下一句狠話,“這有什麼難的,直接上 String 類的 split()
方法不就拉到了!”假如你真的這麼覺得,那可要注意了,事情遠沒這麼簡單。
來來來,搬個小板凳坐下。
假如現在有這樣一串字符“沉默王二,一枚有趣的程序員”,需要按照中文的逗號“,”進行拆分,這意味着第一串字符爲逗號前面的“沉默王二”,第二串字符爲逗號後面的“一枚有趣的程序員”(這不廢話)。另外,在拆分之前,要先進行檢查,判斷一下這串字符是否包含逗號,否則應該拋出異常。
public class Test {
public static void main(String[] args) {
String cmower = "沉默王二,一枚有趣的程序員";
if (cmower.contains(",")) {
String [] parts = cmower.split(",");
System.out.println("第一部分:" + parts[0] +" 第二部分:" + parts[1]);
} else {
throw new IllegalArgumentException("當前字符串沒有包含逗號");
}
}
}
這段代碼看起來挺嚴謹的,對吧?程序輸出的結果完全符合預期:
第一部分:沉默王二 第二部分:一枚有趣的程序員
這是建立在字符串是確定的情況下,最重要的是分隔符是確定的。否則,麻煩就來了。
大約有 12 種英文特殊符號,如果直接拿這些特殊符號替換上面代碼中的分隔符(中文逗號),這段程序在運行的時候就會出現以下提到的錯誤。
-
反斜槓
\
(ArrayIndexOutOfBoundsException) -
插入符號
^
(同上) -
美元符號
$
(同上) -
逗點
.
(同上) -
豎線
|
(正常,沒有出錯) -
問號
?
(PatternSyntaxException) -
星號
*
(同上) -
加號
+
(同上) -
左小括號或者右小括號
()
(同上) -
左方括號或者右方括號
[]
(同上) -
左大括號或者右大括號
{}
(同上)
看到這,可能有小夥伴會說,“這不是鑽牛角尖嘛”,不不不,做技術就應該秉持嚴謹的態度,否則,老大會給你的績效打低分的——獎金拿得少,可不是好滋味。
那遇到特殊符號該怎麼辦呢?上正則表達式唄。
正則表達式是一組由字母和符號組成的特殊文本,它可以用來從文本中找出滿足你想要的格式的句子。
那可能又有小夥伴說,“正則表達式那麼多,我記不住啊!”別擔心,我已經替你想好對策了。
下面這個鏈接是 GitHub 上學習正則表達式的一個在線文檔,非常詳細。遇到正則表達式的時候,掏出這份手冊就完事了。記不住那麼多正則表達式沒關係啊,活學活用唄。
https://github.com/cdoco/learn-regex-zh
除了這份文檔,還有一份:
https://github.com/cdoco/common-regex
作者收集了一些在平時項目開發中經常用到的正則表達式,可以直接拿來用,妙啊。
解決了心病之後,我們來用英文逗點“.”來替換一下分隔符:
String cmower = "沉默王二.一枚有趣的程序員";
if (cmower.contains(".")) {
String [] parts = cmower.split("\\.");
System.out.println("第一部分:" + parts[0] +" 第二部分:" + parts[1]);
}
在使用 split()
方法的時候,就需要使用正則表達式 \\.
來替代特殊字符英文逗點“.”了。爲什麼用兩個反斜槓呢?因爲它本身就是一個特殊字符,需要先轉義。
也可以使用字符類 []
來包含英文逗點“.”,它也是一個正則表達式,用來匹配方括號中包含的任意字符。
cmower.split("[.]");
除此之外, 還可以使用 Pattern 類的 quote()
方法來包裹英文逗點“.”,該方法會返回一個使用 \Q\E
包裹的字符串。
此時, String.split()
方法的使用示例如下所示:
String [] parts = cmower.split(Pattern.quote("."));
當通過調試模式進入 String.split()
方法源碼的話,會發現以下細節:
return Pattern.compile(regex).split(this, limit);
String 類的 split()
方法調用了 Pattern 類的 split()
方法。也就意味着,我們拆分字符串有了新的選擇,可以不使用 String 類的 split()
方法了。
public class TestPatternSplit {
/**
* 使用預編譯功能,提高效率
*/
private static Pattern twopart = Pattern.compile("\\.");
public static void main(String[] args) {
String [] parts = twopart.split("沉默王二.一枚有趣的程序員");
System.out.println("第一部分:" + parts[0] +" 第二部分:" + parts[1]);
}
}
除此之外,還可以使用 Pattern 配合 Matcher 類進行字符串拆分,這樣做的好處是可以對要拆分的字符串進行一些嚴格的限制,來看一段示例代碼:
public class TestPatternMatch {
/**
* 使用預編譯功能,提高效率
*/
private static Pattern twopart = Pattern.compile("(.+)\\.(.+)");
public static void main(String[] args) {
checkString("沉默王二.一枚有趣的程序員");
checkString("沉默王二.");
checkString(".一枚有趣的程序員");
}
private static void checkString(String str) {
Matcher m = twopart.matcher(str);
if (m.matches()) {
System.out.println("第一部分:" + m.group(1) + " 第二部分:" + m.group(2));
} else {
System.out.println("不匹配");
}
}
}
這時候,正則表達式爲 (.+)\\.(.+)
,意味着可以把字符串按照英文逗點拆分成一個字符組,英文小括號 ()
的作用就在於此(可以查看我之前提供的正則表達式手冊)。
由於模式是確定的,所以可以把 Pattern 表達式放在 main()
方法外面,通過 static 的預編譯功能提高程序的效率。
來看一下程序的輸出結果:
第一部分:沉默王二 第二部分:一枚有趣的程序員
不匹配
不匹配
不過,使用 Matcher 來匹配一些簡單的字符串時相對比較沉重一些,使用 String 類的 split()
仍然是首選,因爲該方法還有其他一些牛逼的功能。
比如說,你想把分隔符包裹在拆分後的字符串的第一部分,可以這樣做:
String cmower = "沉默王二,一枚有趣的程序員";
if (cmower.contains(",")) {
String [] parts = cmower.split("(?<=,)");
System.out.println("第一部分:" + parts[0] +" 第二部分:" + parts[1]);
}
程序輸出的結果如下所示:
第一部分:沉默王二, 第二部分:一枚有趣的程序員
可以看到分隔符“,”包裹在了第一部分,如果希望包裹在第二部分,可以這樣做:
String [] parts = cmower.split("(?=,)");
可能有些小夥伴很好奇, ?<=
和 ?=
是什麼東東啊?它其實是正則表達式中的斷言模式。
溫馨提醒:如果對斷言模式比較生疏的話,可以查看我之前提供的正則表達式手冊。
另外,假如說字符串中包含了多個分隔符,而我們只需要 2 個的話,還可以這樣做:
String cmower = "沉默王二,一枚有趣的程序員,寵愛他";
if (cmower.contains(",")) {
String [] parts = cmower.split(",", 2);
System.out.println("第一部分:" + parts[0] +" 第二部分:" + parts[1]);
}
split()
方法可以傳遞 2 個參數,第一個爲分隔符,第二個爲拆分的字符串個數。查看該方法源碼的話,你就可以看到以下內容:
直接 substring()
到原字符串的末尾,也就是說,第二個分隔符處不再拆分。然後就 break 出循環了。來看一下程序輸出的結果:
第一部分:沉默王二 第二部分:一枚有趣的程序員,寵愛他
好了,我親愛的讀者朋友,以上就是本文的全部內容了。是不是突然感覺拆分個字符串真的挺講究的?
------------------
公衆號:沉默王二(ID:cmower)
CSDN:沉默王二
這是一個有顏值卻靠才華喫飯的程序員,你知道,他的文章風趣幽默,讀起來就好像花錢一樣爽快。
長按下圖二維碼關注,你將感受到一個有趣的靈魂, 且每篇文章都有乾貨。
-------------- --- -
原創不易,莫要白票,如果覺得有點用的話,請毫不留情地轉發朋友圈吧 ,因爲這將是我寫作更多優質文章的最強動力。