提到 Java 拆分字符串,我猜你十有八九會撂下一句狠話,「這有什麼難的,直接上 String 類的 split()
方法不就拉到了!」假如你真的這麼以爲,那可要注意了,事情遠沒這麼簡單。java
來來來,搬個小板凳坐下。git
假如如今有這樣一串字符「沉默王二,一枚有趣的程序員」,須要按照中文的逗號「,」進行拆分,這意味着第一串字符爲逗號前面的「沉默王二」,第二串字符爲逗號後面的「一枚有趣的程序員」(這不廢話)。另外,在拆分以前,要先進行檢查,判斷一下這串字符是否包含逗號,不然應該拋出異常。程序員
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("當前字符串沒有包含逗號"); } } }
這段代碼看起來挺嚴謹的,對吧?程序輸出的結果徹底符合預期:github
第一部分:沉默王二 第二部分:一枚有趣的程序員
這是創建在字符串是肯定的狀況下,最重要的是分隔符是肯定的。不然,麻煩就來了。面試
大約有 12 種英文特殊符號,若是直接拿這些特殊符號替換上面代碼中的分隔符(中文逗號),這段程序在運行的時候就會出現如下提到的錯誤。正則表達式
\
(ArrayIndexOutOfBoundsException)^
(同上)$
(同上).
(同上)|
(正常,沒有出錯)?
(PatternSyntaxException)*
(同上)+
(同上)()
(同上)[]
(同上){}
(同上)看到這,可能有小夥伴會說,「這不是鑽牛角尖嘛」,不不不,作技術就應該秉持嚴謹的態度,不然,老大會給你的績效打低分的——獎金拿得少,可不是好滋味。學習
那遇到特殊符號該怎麼辦呢?上正則表達式唄。this
正則表達式是一組由字母和符號組成的特殊文本,它能夠用來從文本中找出知足你想要的格式的句子。
那可能又有小夥伴說,「正則表達式那麼多,我記不住啊!」別擔憂,我已經替你想好對策了。spa
下面這個連接是 GitHub 上學習正則表達式的一個在線文檔,很是詳細。遇到正則表達式的時候,掏出這份手冊就完事了。記不住那麼多正則表達式不要緊啊,活學活用唄。3d
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 出循環了。來看一下程序輸出的結果:
第一部分:沉默王二 第二部分:一枚有趣的程序員,寵愛他
好了,我親愛的讀者朋友,以上就是本文的所有內容了。是否是忽然感受拆分個字符串真的挺講究的?我是沉默王二,一枚有趣的程序員。原創不易,莫要白票,請你爲本文點贊個吧,這將是我寫做更多優質文章的最強動力。
本文 GitHub 已經收錄,有大廠面試完整考點,歡迎 Star。