咦规阀,Java拆分個(gè)字符串都這么講究

提到 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)力。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末宗侦,一起剝皮案震驚了整個(gè)濱河市愚臀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌矾利,老刑警劉巖姑裂,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異男旗,居然都是意外死亡舶斧,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)察皇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)茴厉,“玉大人,你說(shuō)我怎么就攤上這事什荣》海” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵稻爬,是天一觀的道長(zhǎng)而账。 經(jīng)常有香客問(wèn)我,道長(zhǎng)因篇,這世上最難降的妖魔是什么泞辐? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮竞滓,結(jié)果婚禮上咐吼,老公的妹妹穿的比我還像新娘。我一直安慰自己商佑,他們只是感情好锯茄,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著茶没,像睡著了一般肌幽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上抓半,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天喂急,我揣著相機(jī)與錄音,去河邊找鬼笛求。 笑死廊移,一個(gè)胖子當(dāng)著我的面吹牛糕簿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播狡孔,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼懂诗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了苗膝?” 一聲冷哼從身側(cè)響起殃恒,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辱揭,沒(méi)想到半個(gè)月后离唐,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡界阁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年侯繁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泡躯。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贮竟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出较剃,到底是詐尸還是另有隱情咕别,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布写穴,位于F島的核電站惰拱,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏啊送。R本人自食惡果不足惜偿短,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望馋没。 院中可真熱鬧昔逗,春花似錦、人聲如沸篷朵。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)声旺。三九已至笔链,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間腮猖,已是汗流浹背鉴扫。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缚够,地道東北人幔妨。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓鹦赎,卻偏偏與公主長(zhǎng)得像谍椅,于是被迫代替她去往敵國(guó)和親误堡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348