60

String.replaceAll()とMatcher.replaceAll()(Regex.Patternから作成されたMatcherオブジェクト上)の間にパフォーマンスの点で既知の違いはありますか?

また、両者の高レベルAPIの違いは何ですか?(不変性、NULLの処理、空の文字列の処理など)

4

7 に答える 7

96

のドキュメントによるとString.replaceAll、メソッドの呼び出しについて次のように述べています。

この形式のメソッドを呼び出すと、str.replaceAll(regex, repl) 式とまったく同じ結果が得られます。

Pattern.compile(regex).matcher(str).replaceAll(repl)

String.replaceAllしたがって、を呼び出してから明示的にaMatcherを作成するまでのパフォーマンスは同じであることが期待できますPattern

編集

コメントで指摘されているように、またはへの1回の呼び出しではパフォーマンスの違いはありませんがreplaceAllStringMatcherの複数の呼び出しを実行する必要がある場合はreplaceAll、コンパイルされたものを保持することが有益であると予想されます。Patternしたがって、比較的高価な正規表現パターンのコンパイルを毎回実行する必要はありません。

于 2009-09-23T16:06:45.203 に答える
30

ソースコードString.replaceAll()

public String replaceAll(String regex, String replacement) {
    return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}

最初にパターンをコンパイルする必要があります。短い文字列で同じパターンを使用して何度も実行する場合は、コンパイルした1つのパターンを再利用するとパフォーマンスが大幅に向上します。

于 2009-09-23T16:08:11.270 に答える
10

Pattern主な違いは、を生成するために使用されるものを保持すると、使用するMatcherたびに正規表現を再コンパイルすることを回避できることです。を通過するStringと、このように「キャッシュ」する機能が得られません。

毎回異なる正規表現がある場合は、Stringクラスを使用しても問題ありませんreplaceAll。同じ正規表現を多くの文字列に適用する場合は、正規表現を作成Patternして再利用します。

于 2009-09-23T16:07:40.727 に答える
6

不変性/スレッドセーフ:コンパイルされたパターンは不変ですが、マッチャーは不変ではありません。(Java正規表現スレッドセーフを参照してください)

空の文字列の処理:replaceAllは、空の文字列を適切に処理する必要があります(空の入力文字列パターンとは一致しません)

コーヒーを作るなど:最後に聞いたのですが、String、Pattern、MatcherのいずれにもそのためのAPI機能はありませんでした。

編集:NULLの処理に関しては、StringとPatternのドキュメントには明示的には記載されていませんが、Stringを予期しているため、NullPointerExceptionがスローされると思われます。

于 2009-09-23T16:15:00.313 に答える
5

の実装は、String.replaceAllあなたが知る必要があるすべてを教えてくれます:

return Pattern.compile(regex).matcher(this).replaceAll(replacement);

(そして、ドキュメントは同じことを言っています。)

キャッシングをチェックしていませんが、パターンを1回Pattern.compileコンパイルし、それへの静的参照を保持する方が、毎回同じパターンで呼び出すよりも効率的であると確信しています。キャッシュがある場合は、効率が少し節約されます。キャッシュがない場合は、大きなキャッシュになる可能性があります。

于 2009-09-23T16:05:55.573 に答える
5

違いは、 String.replaceAll() が呼び出されるたびに正規表現をコンパイルすることです。コンパイルされた正規表現を自動的にキャッシュする .NET の静的 Regex.Replace() メソッドに相当するものはありません。通常、replaceAll() は 1 回だけ実行しますが、特にループ内で同じ正規表現を使用して繰り返し呼び出す場合は、Pattern オブジェクトを作成し、Matcher メソッドを使用する必要があります。

事前に Matcher を作成し、その reset() メソッドを使用して、使用ごとに再ターゲットすることもできます。

Matcher m = Pattern.compile(regex).matcher("");
for (String s : targets)
{
  System.out.println(m.reset(s).replaceAll(repl));
}

もちろん、Matcher を再利用することによるパフォーマンス上のメリットは、Pattern を再利用することほど大きくはありません。

于 2009-09-23T16:35:53.923 に答える