提到 Java 拆分字符串恒序,我猜你十有八九會(huì)撂下一句狠話(huà),“這有什么難的谁撼,直接上 String 類(lèi)的 split()
方法不就拉到了歧胁!”假如你真的這么覺(jué)得,那可要注意了厉碟,事情遠(yuǎn)沒(méi)這么簡(jiǎn)單喊巍。
來(lái)來(lái)來(lái),搬個(gè)小板凳坐下箍鼓。
假如現(xiàn)在有這樣一串字符“沉默王二崭参,一枚有趣的程序員”,需要按照中文的逗號(hào)“款咖,”進(jìn)行拆分何暮,這意味著第一串字符為逗號(hào)前面的“沉默王二”,第二串字符為逗號(hào)后面的“一枚有趣的程序員”(這不廢話(huà))铐殃。另外海洼,在拆分之前,要先進(jìn)行檢查背稼,判斷一下這串字符是否包含逗號(hào)贰军,否則應(yīng)該拋出異常。
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("當(dāng)前字符串沒(méi)有包含逗號(hào)");
}
}
}
這段代碼看起來(lái)挺嚴(yán)謹(jǐn)?shù)模瑢?duì)吧贰盗?程序輸出的結(jié)果完全符合預(yù)期:
第一部分:沉默王二 第二部分:一枚有趣的程序員
這是建立在字符串是確定的情況下许饿,最重要的是分隔符是確定的。否則舵盈,麻煩就來(lái)了陋率。
大約有 12 種英文特殊符號(hào),如果直接拿這些特殊符號(hào)替換上面代碼中的分隔符(中文逗號(hào))秽晚,這段程序在運(yùn)行的時(shí)候就會(huì)出現(xiàn)以下提到的錯(cuò)誤瓦糟。
- 反斜杠
\
(ArrayIndexOutOfBoundsException) - 插入符號(hào)
^
(同上) - 美元符號(hào)
$
(同上) - 逗點(diǎn)
.
(同上) - 豎線
|
(正常,沒(méi)有出錯(cuò)) - 問(wèn)號(hào)
?
(PatternSyntaxException) - 星號(hào)
*
(同上) - 加號(hào)
+
(同上) - 左小括號(hào)或者右小括號(hào)
()
(同上) - 左方括號(hào)或者右方括號(hào)
[]
(同上) - 左大括號(hào)或者右大括號(hào)
{}
(同上)
看到這赴蝇,可能有小伙伴會(huì)說(shuō)菩浙,“這不是鉆牛角尖嘛”,不不不句伶,做技術(shù)就應(yīng)該秉持嚴(yán)謹(jǐn)?shù)膽B(tài)度劲蜻,否則,老大會(huì)給你的績(jī)效打低分的——獎(jiǎng)金拿得少考余,可不是好滋味先嬉。
那遇到特殊符號(hào)該怎么辦呢?上正則表達(dá)式唄楚堤。
正則表達(dá)式是一組由字母和符號(hào)組成的特殊文本疫蔓,它可以用來(lái)從文本中找出滿(mǎn)足你想要的格式的句子。
那可能又有小伙伴說(shuō)钾军,“正則表達(dá)式那么多鳄袍,我記不住熬钜吏恭!”別擔(dān)心,我已經(jīng)替你想好對(duì)策了重罪。
下面這個(gè)鏈接是 GitHub 上學(xué)習(xí)正則表達(dá)式的一個(gè)在線文檔樱哼,非常詳細(xì)。遇到正則表達(dá)式的時(shí)候剿配,掏出這份手冊(cè)就完事了搅幅。記不住那么多正則表達(dá)式?jīng)]關(guān)系啊,活學(xué)活用唄呼胚。
https://github.com/cdoco/learn-regex-zh
除了這份文檔茄唐,還有一份:
https://github.com/cdoco/common-regex
作者收集了一些在平時(shí)項(xiàng)目開(kāi)發(fā)中經(jīng)常用到的正則表達(dá)式,可以直接拿來(lái)用,妙啊沪编。
解決了心病之后呼盆,我們來(lái)用英文逗點(diǎn)“.”來(lái)替換一下分隔符:
String cmower = "沉默王二.一枚有趣的程序員";
if (cmower.contains(".")) {
String [] parts = cmower.split("\\.");
System.out.println("第一部分:" + parts[0] +" 第二部分:" + parts[1]);
}
在使用 split()
方法的時(shí)候,就需要使用正則表達(dá)式 \\.
來(lái)替代特殊字符英文逗點(diǎn)“.”了蚁廓。為什么用兩個(gè)反斜杠呢访圃?因?yàn)樗旧砭褪且粋€(gè)特殊字符,需要先轉(zhuǎn)義相嵌。
也可以使用字符類(lèi) []
來(lái)包含英文逗點(diǎn)“.”腿时,它也是一個(gè)正則表達(dá)式,用來(lái)匹配方括號(hào)中包含的任意字符饭宾。
cmower.split("[.]");
除此之外批糟, 還可以使用 Pattern 類(lèi)的 quote()
方法來(lái)包裹英文逗點(diǎn)“.”,該方法會(huì)返回一個(gè)使用 \Q\E
包裹的字符串看铆。
此時(shí)跃赚,String.split()
方法的使用示例如下所示:
String [] parts = cmower.split(Pattern.quote("."));
當(dāng)通過(guò)調(diào)試模式進(jìn)入 String.split()
方法源碼的話(huà),會(huì)發(fā)現(xiàn)以下細(xì)節(jié):
return Pattern.compile(regex).split(this, limit);
String 類(lèi)的 split()
方法調(diào)用了 Pattern 類(lèi)的 split()
方法性湿。也就意味著纬傲,我們拆分字符串有了新的選擇,可以不使用 String 類(lèi)的 split()
方法了肤频。
public class TestPatternSplit {
/**
* 使用預(yù)編譯功能叹括,提高效率
*/
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 類(lèi)進(jìn)行字符串拆分宵荒,這樣做的好處是可以對(duì)要拆分的字符串進(jìn)行一些嚴(yán)格的限制汁雷,來(lái)看一段示例代碼:
public class TestPatternMatch {
/**
* 使用預(yù)編譯功能,提高效率
*/
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("不匹配");
}
}
}
這時(shí)候报咳,正則表達(dá)式為 (.+)\\.(.+)
侠讯,意味著可以把字符串按照英文逗點(diǎn)拆分成一個(gè)字符組,英文小括號(hào) ()
的作用就在于此(可以查看我之前提供的正則表達(dá)式手冊(cè))暑刃。
由于模式是確定的厢漩,所以可以把 Pattern 表達(dá)式放在 main()
方法外面,通過(guò) static 的預(yù)編譯功能提高程序的效率岩臣。
來(lái)看一下程序的輸出結(jié)果:
第一部分:沉默王二 第二部分:一枚有趣的程序員
不匹配
不匹配
不過(guò)溜嗜,使用 Matcher 來(lái)匹配一些簡(jiǎn)單的字符串時(shí)相對(duì)比較沉重一些,使用 String 類(lèi)的 split()
仍然是首選架谎,因?yàn)樵摲椒ㄟ€有其他一些牛逼的功能炸宵。
比如說(shuō),你想把分隔符包裹在拆分后的字符串的第一部分谷扣,可以這樣做:
String cmower = "沉默王二土全,一枚有趣的程序員";
if (cmower.contains(",")) {
String [] parts = cmower.split("(?<=,)");
System.out.println("第一部分:" + parts[0] +" 第二部分:" + parts[1]);
}
程序輸出的結(jié)果如下所示:
第一部分:沉默王二裹匙, 第二部分:一枚有趣的程序員
可以看到分隔符“野哭,”包裹在了第一部分,如果希望包裹在第二部分幻件,可以這樣做:
String [] parts = cmower.split("(?=拨黔,)");
可能有些小伙伴很好奇,?<=
和 ?=
是什么東東按铝ぁ篱蝇?它其實(shí)是正則表達(dá)式中的斷言模式。
溫馨提醒:如果對(duì)斷言模式比較生疏的話(huà)徽曲,可以查看我之前提供的正則表達(dá)式手冊(cè)零截。
另外,假如說(shuō)字符串中包含了多個(gè)分隔符秃臣,而我們只需要 2 個(gè)的話(huà)涧衙,還可以這樣做:
String cmower = "沉默王二,一枚有趣的程序員奥此,寵愛(ài)他";
if (cmower.contains("弧哎,")) {
String [] parts = cmower.split(",", 2);
System.out.println("第一部分:" + parts[0] +" 第二部分:" + parts[1]);
}
split()
方法可以傳遞 2 個(gè)參數(shù)稚虎,第一個(gè)為分隔符撤嫩,第二個(gè)為拆分的字符串個(gè)數(shù)。查看該方法源碼的話(huà)蠢终,你就可以看到以下內(nèi)容:
直接 substring()
到原字符串的末尾序攘,也就是說(shuō),第二個(gè)分隔符處不再拆分寻拂。然后就 break 出循環(huán)了程奠。來(lái)看一下程序輸出的結(jié)果:
第一部分:沉默王二 第二部分:一枚有趣的程序員,寵愛(ài)他
好了祭钉,我親愛(ài)的讀者朋友瞄沙,以上就是本文的全部?jī)?nèi)容了撩鹿。是不是突然感覺(jué)拆分個(gè)字符串真的挺講究的?
我是沉默王二禀倔,一枚有趣的程序員浦楣。如果覺(jué)得文章對(duì)你有點(diǎn)幫助,請(qǐng)微信搜索「 沉默王二 」第一時(shí)間閱讀币旧。
回復(fù)【666】更有我為你精心準(zhǔn)備的 500G 高清教學(xué)視頻(已分門(mén)別類(lèi))。本文 GitHub 已經(jīng)收錄,有大廠面試完整考點(diǎn)扒接,歡迎 Star。
原創(chuàng)不易,莫要白票钾怔,請(qǐng)你為本文點(diǎn)贊個(gè)吧碱呼,這將是我寫(xiě)作更多優(yōu)質(zhì)文章的最強(qiáng)動(dòng)力。