天天看點

咦,Java拆分個字元串都這麼講究(1)

提到 Java 拆分字元串,我猜你十有八九會撂下一句狠話,“這有什麼難的,直接上 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 包裹的字元串。

咦,Java拆分個字元串都這麼講究(1)

此時,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]);
    }
}