5

以我刚刚回答的问题的代码为例

从字符串开始

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", "@");
4

2 回答 2

5

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

两种情况下的搜索效率是一样的;区别仅在于捕获的内容。因此,性能上的整体差异将归结为替换字符串内容的差异:在第一种情况下,将两个字符串组合在一起形成替换,而在第二种情况下,只使用一个字符串。从理论上讲,第一种情况应该需要更多的工作,但在实践中,这种差异不太可能很明显。

编辑:正如acheong87的测试所示,在 Java 中使用正向前瞻的效率降低了近 50%。此外,这种低效率似乎并不是特定于 Java 的(尽管它在 Java 中的幅度是压倒性的:相当于acheong87's的 C# 程序在 Mono 下显示出大约 24% 的速度下降,在 Windows 下显示出大约 21% 的速度)。

我想这个练习的带回家的教训是,表达式的理论近似等效并不能保证实践中的等效时间:没有替代实际实现的分析。

于 2012-10-31T08:06:53.560 回答
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% 的工作!我怀疑可能是这种情况,因为在传递了感兴趣的字符之后,反向引用需要返回以检查断言是否为真。

于 2012-10-31T08:34:31.610 回答