首页 » 编写高质量代码:改善Java程序的151个建议 » 编写高质量代码:改善Java程序的151个建议全文在线阅读

《编写高质量代码:改善Java程序的151个建议》建议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、+、?、()、、{}等符号的正则表达式,然后告诉你这是一个“这样,这样……”的字符串查找,你是不是要崩溃了?这代码只有上帝才能看懂了!

注意 正则表达式是恶魔,威力巨大,但难以控制。