Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的正则表达式速度_Java_Regex_Optimization - Fatal编程技术网

Java中的正则表达式速度

Java中的正则表达式速度,java,regex,optimization,Java,Regex,Optimization,大量字符串的一些示例挂钟时间: .split("[^a-zA-Z]"); // .44 seconds .split("[^a-zA-Z]+"); // .47 seconds .split("\\b+"); // 2 seconds 有什么解释能解释这一急剧增长的原因吗?我可以将处理器中执行的[^a-zA-Z]模式想象为一组四个比较操作,只有在真实情况下才会执行所有四个比较操作。那\b呢?有人对此有什么看法吗?\b是一种零宽度断言,它与[^a-Za-z]有根本不同。因为\b是作为if/the

大量字符串的一些示例挂钟时间:

.split("[^a-zA-Z]"); // .44 seconds
.split("[^a-zA-Z]+"); // .47 seconds
.split("\\b+"); // 2 seconds

有什么解释能解释这一急剧增长的原因吗?我可以将处理器中执行的[^a-zA-Z]模式想象为一组四个比较操作,只有在真实情况下才会执行所有四个比较操作。那\b呢?有人对此有什么看法吗?

\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+”的编译比其他模式的编译要慢,您可以在这里使用预编译的习惯用法来测试它,尽管我觉得这不太可能作为一种解释


有关regex性能的更多信息,请阅读Russ Cox的这些文章并查看。

首先,在一个或多个零宽度断言上拆分是没有意义的!Java的正则表达式在理智的优化方面不是很聪明,我也很仁慈

第二,不要在Java中使用
\b
:它混乱不堪,与
\w
不同步


关于这一点的更完整的解释,特别是如何使用Unicode,请参阅。

我不知道Java的正则表达式是否支持Unicode(如果它们不支持Unicode,我会感到惊讶),那么
\b
将是一个比仅仅
[a-zA-Z]
甚至
[a-zA-Z0-9.
更复杂的检查……这是错误的
\b
从来都不是指
[^a-zA-Z0-9][/code>。首先,它有宽度,而
\b
没有宽度。
\b
真正的意思是
(?:(?\w
定义,当然。Java没有,所以你必须使用我的重写函数或`(?:(?@Dean:是的,
\b
是Unicode感知的(以其自身有趣的方式),这是一个复杂得多的测试。它必须应用于每个位置,因为通过或失败,它从不使用任何字符。
split
只编译一次模式:
publicstring[]split(stringregex,int-limit){return pattern.compile(regex).split(this,limit);}
来自
j2se/src/share/altclasses/java/lang/String。java
@Platinum:请记住有两种拆分方法:and。反复调用
Pattern#split
不会导致重新编译模式。反复调用
String#split#code>会导致重新编译模式。所有这些时间看起来都很简单大约3个数量级太大了。您的输入数据看起来像什么?它看起来像几百万行分割。这是正确的数量级。空间学员时刻;忘记了\b是零宽度。