大量字符串的一些示例挂钟时间:
.split("[^a-zA-Z]"); // .44 seconds
.split("[^a-zA-Z]+"); // .47 seconds
.split("\\b+"); // 2 seconds
对戏剧性增加的任何解释?我可以想象在处理器中完成的[^ a-zA-Z]模式是一组四个比较操作,只有当它是真实情况时才会发生这四个比较操作。 \ b怎么样?任何人都有什么可以权衡的吗?
答案 0 :(得分:4)
首先,分割一个或多个零宽度断言是没有意义的! Java的正则表达式并不是非常聪明 - 而且我是慈善事业 - 关于理智的优化。
其次,永远不要在Java中使用\b
:它与\w
混乱并且不同步。
有关此内容的更完整说明,尤其是如何使用Unicode,请参阅this answer。
答案 1 :(得分:-1)
\b
是零宽度断言,与[^A-Za-z]
根本不同。因为\b
是作为if / then实现的(请参阅下面的tchrist评论),所以检查每个字符串中的每个字母可能需要做更多的工作。此外,加号导致回溯,这将使该成本倍增。
此外,当您在单词边界上进行拆分时,与仅在[^a-zA-Z]+
上拆分相比,您将在更多地方匹配。这将导致分配更多字符串,这也将花费更多时间。
要看到这一点,请尝试以下程序:
import java.lang.String;
class RegexDemo {
private static void testSplit(String msg, String re) {
String[] pieces = "the quick brown fox".split(re);
System.out.println(msg);
for (String s : pieces) {
System.out.println(s);
}
System.out.println("----");
}
public static void main(String args[]) {
testSplit("boundary:", "\\b+");
testSplit("not alpha:", "[^A-Za-z]+");
}
}
可能不相关,当您使用String.split()时,必须为每次使用编译正则表达式。 如果您将正则表达式预编译为模式,例如,
Pattern boundary = Pattern.compile("\\b+");
然后使用boundary.split(testString)
进行拆分,您将节省为每个测试字符串编译正则表达式的成本。所以,可以想象编译" \ b +"比其他模式的编译慢,你可以在这里使用预编译的习惯用法进行测试,虽然这似乎不太可能是我的解释。
有关正则表达式性能的更多信息,请阅读Russ Cox http://swtch.com/~rsc/regexp/的这些文章并查看http://www.regular-expressions.info/。