讀古今文學網 > 編寫高質量代碼:改善Java程序的151個建議 > 建議57:推薦在複雜字符串操作中使用正則表達式 >

建議57:推薦在複雜字符串操作中使用正則表達式

字符串的操作,諸如追加、合併、替換、倒序、分割等,都是在編碼過程中經常用到的,而且Java也提供了append、replace、reverse、split等方法來完成這些操作,它們使用起來也確實方便,但是更多的時候,需要使用正則表達式來完成複雜的處理,我們來看一個例子:統計一篇文章中英文單詞的數量,很簡單吧?代碼如下:


public static void main(Stringargs){

//接收鍵盤輸入

Scanner input=new Scanner(System.in);

while(input.hasNext()){

String str=input.nextLine();

//使用split方法分隔後統計

int wordsCount=str.split("").length;

System.out.println(str+"單詞數:"+wordsCount);

}

}


使用split方法根據空格來分割單詞,然後計算分隔後的數組長度,這種方法可靠嗎?可行嗎?我們來看輸出:


Today is Monday

Today is Monday單詞數:3

Today is Monday

Today is Monday單詞數:4

Today is Monday?No!

Today is Monday?No!單詞數:3

I'm Ok.

I'm Ok.單詞數:2


注意看輸出,除了第一個輸入"Todady is Monay"正確外,其他都是錯誤的!第二條輸入中單詞"Monday"前有2個連續的空格,第三條輸入中"NO"單詞的前後都沒有空格,最後一個輸入則沒有把連寫符號「'」考慮進去,這樣統計出來的單詞數量肯定錯誤一堆,那怎麼做才合理呢?

如果考慮使用一個循環來處理這樣的「異常」情況,會使程序的穩定性變差,而且要考慮太多太多的因素,這讓程序的複雜性也大大提高了。那如何處理呢?可以考慮使用正則表達式,代碼如下:


public static void main(Stringargs){

//接收鍵盤輸入

Scanner input=new Scanner(System.in);

while(input.hasNext()){

String str=input.nextLine();

//正則表達式對像

Pattern pattern=Pattern.compile("\\b\\w+\\b");

//生成匹配器

Matcher matcher=pattern.matcher(str);

//記錄單詞數量

int wordsCount=0;

//遍歷查找匹配,統計單詞數量

while(matcher.find()){

wordsCount++;

}

System.out.println(str+"單詞數:"+wordsCount);

}

}


準不準確,我們來看相同的輸入所產生的結果:


Today is Monday

Today is Monday單詞數:3

Today is Monday

Today is Monday單詞數:3

Today is Monday?No!

Today is Monday?No!單詞數:4

I'm Ok.

I'm Ok.單詞數:3


每項的輸出都是準確的,而且程序也不複雜,先生成一個正則表達式對象,然後使用匹配器進行匹配,之後通過一個while循環統計匹配的數量。需要說明的是,在Java的正則表達式中"\b"表示的是一個單詞的邊界,它是一個位置界定符,一邊為字符或數字,另外一邊則非字符或數字,例如"A"這樣一個輸入就有兩個邊界,即單詞"A"的左右位置,這也就說明了為什麼要加上"\w"(它表示的是字符或數字)。

正則表達式在字符串的查找、替換、剪切、複製、刪除等方面有著非凡的作用,特別是面對大量的文本字符需要處理(如需要讀取大量的LOG日誌)時,使用正則表達式可以大幅地提高開發效率和系統性能,但是正則表達式是一個惡魔(Regular Expressions is evil),它會使程序難以讀懂,想想看,寫一個包含^、$、\A、\s、\Q、+、?、()、、{}等符號的正則表達式,然後告訴你這是一個「這樣,這樣……」的字符串查找,你是不是要崩潰了?這代碼只有上帝才能看懂了!

注意 正則表達式是惡魔,威力巨大,但難以控制。