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 

@すべての 4 桁の数字の後のスペースを次のようなものに置き換えたい場合はどうなるでしょうか。

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

私のテスト方法論は粗雑で、欠陥がある可能性があることを認めます (さらに、私は 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 に答える
5

最初の例には後方参照はありません。これは、出力内の番号付きキャプチャ グループへの参照です。

どちらの場合も検索の効率は同じです。違いはキャプチャされるものだけです。したがって、パフォーマンスの全体的な違いは、文字列コンテンツの置換の違いに要約されます。最初のケースでは、2 つの文字列が結合されて置換が形成されますが、2 番目のケースでは、1 つの文字列のみが使用されます。理論的には、最初のケースではもう少し多くの作業が必要になるはずですが、実際には違いが顕著になる可能性は低いです。

編集: acheong87によるテストが示すように、正の先読みを使用すると、Java での効率が 50% 近く低下します。さらに、この非効率性は Java 固有のものではないようです (ただし、Java でのその大きさは圧倒的です:に相当する C# プログラムacheong87は、Mono で約 24%、Windows で約 21% の速度低下を示します)

この演習から得られる教訓は、式が理論的にほぼ同等であっても、実際には同等のタイミングが保証されないということです。実際の実装のプロファイリングに代わるものはありません。

于 2012-10-31T08:06:53.560 に答える