使用积极的后视或后引用是否更有效?

时间:2012-10-31 07:56:40

标签: java regex

Using the code of a question I just answered as an example

从字符串

开始
30-Nov-2012 30-Nov-2012 United Kingdom, 31-Oct-2012 31-Oct-2012 United
Arab Emirates, 29-Oct-2012 31-Oct-2012 India 

如果我们想用@替换每个四位数后面的空格,以便最终得到类似的内容,那该怎么办?

30-Nov-2012@30-Nov-2012@United Kingdom, 31-Oct-2012@31-Oct-2012@United
Arab Emirates, 29-Oct-2012@31-Oct-2012@India  

使用反向引用而不是正向背后(如果有的话)效率是多少?

向后引用:

inputString.replaceAll("(\\d{4})\\s", "$1@");

积极向后看:

inputString.replaceAll("(?<=\\d{4})\\s", "@");

2 个答案:

答案 0 :(得分:5)

第一个示例中没有反向引用,它是对输出中带编号的捕获组的引用。

两种情况下的搜索效率都是一样的;区别仅在于捕获的内容。因此,性能的总体差异将归结为替换字符串内容的差异:在第一种情况下,两个字符串组合形成替换,而在第二种情况下,仅使用一个字符串。从理论上讲,第一种情况应该需要稍微多一点的工作,但实际上差异不大可能是显而易见的。

编辑:正如acheong87所显示的那样,使用正向前瞻在Java中效率将降低近50%。此外,这种低效率似乎并不是特定于Java的(虽然它在Java中的重要性是压倒性的:a C# program equivalent to acheong87's显示Mono下降约24%,Windows下约21%。

我认为本练习的主要内容是表达式的理论近似等价并不能保证实际中的等效时间:没有替代实际实现的概要分析。

答案 1 :(得分:5)

我承认我的测试方法很粗糙,可能存在缺陷(此外我不懂Java,只学习写这个答案),但我的初步证据证明与@ dasblinkenlight的答案相反。我运行了以下代码:

import java.util.*;
import java.lang.*;

class Main
{
    private static void test (String regex, String replace, int repetitions)
    {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < repetitions; i++)
        {
            String str = "30-Nov-2012 United Kingdom, 31-Oct-2012 31-Oct-2012 United Arab Emirates, 29-Oct-2012 31-Oct-2012 India, ";
            str.replaceAll(regex, replace);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Execution time: " + Long.toString(endTime - startTime));
    }

    public static void main (String[] args) throws java.lang.Exception
    {
        test("(\\d{4})\\s", "$1@", 10000);
        test("(?<=\\d{4})\\s", "@", 10000);
        test("(\\d{4})\\s", "$1@", 10000);
        test("(?<=\\d{4})\\s", "@", 10000);
        test("(\\d{4})\\s", "$1@", 10000);
        test("(?<=\\d{4})\\s", "@", 10000);
        test("(\\d{4})\\s", "$1@", 10000);
        test("(?<=\\d{4})\\s", "@", 10000);
    }
}

...此处,http://ideone.com/WkHLMN,输出结果为:

Execution time: 164
Execution time: 140
Execution time: 96
Execution time: 135
Execution time: 95
Execution time: 133
Execution time: 94
Execution time: 130

将第一组案例忽略为与初始化有关的异常值,其余案例似乎表明后者表达式,使用正向后看断言,可能会多做50%的工作量!我怀疑情况可能就是这样,因为反向引用需要 back 检查断言是否为真,传递感兴趣的字符后。