非常に簡単な質問ですが、これは、Javaの複雑さに慣れるC/C++の人から来ています。
答えを得るために、jUnitと自分自身のいくつかのパフォーマンステストを実行できることを理解しています。しかし、私はこれがそこにあるかどうか疑問に思っています。
パフォーマンスに関して、String.replaceAll()とMatcher.replaceAll()(Regex.Patternから作成されたMatcherオブジェクト上)の間に既知の違いはありますか?
また、両者の高レベルAPI 'ishの違いは何ですか? (不変性、NULLの処理、空の文字列の処理、コーヒーの製造など)
String.replaceAll()
のソースコード:
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
最初にパターンをコンパイルする必要があります-短い文字列で同じパターンを使用して何度も実行する場合、コンパイルされたパターンを再利用するとパフォーマンスが大幅に向上します。
主な違いは、Pattern
の生成に使用されるMatcher
を保持する場合、使用するたびに正規表現の再コンパイルを回避できることです。 String
を通過すると、このような「キャッシュ」機能を取得できません。
毎回異なる正規表現がある場合は、String
クラスのreplaceAll
を使用するのが適切です。同じ正規表現を多くの文字列に適用する場合は、1つのPattern
を作成して再利用します。
不変性/スレッドセーフティ:コンパイルされたパターンは不変ですが、マッチャーは不変です。 ( Is Java Regex Thread Safe? を参照)
空の文字列の処理:replaceAllは空の文字列を適切に処理する必要があります(空の入力文字列パターンとは一致しません)
コーヒーなどを作る:最後に聞いたところ、文字列もパターンもマッチャーもそのためのAPI機能を持っていませんでした。
編集:NULLの処理に関しては、StringとPatternのドキュメントは明示的に言っていませんが、Stringを期待しているため、NullPointerExceptionがスローされると思われます。
違いは、String.replaceAll()が呼び出されるたびに正規表現をコンパイルすることです。コンパイル済みの正規表現を自動的にキャッシュする.NETの静的Regex.Replace()メソッドに相当するものはありません。通常、replaceAll()は一度しか実行しませんが、特にループ内で同じ正規表現で繰り返し呼び出す場合は、Patternオブジェクトを作成してMatcherメソッドを使用する必要があります。
事前にMatcherを作成し、reset()メソッドを使用して、使用するたびにリターゲットすることもできます。
Matcher m = Pattern.compile(regex).matcher("");
for (String s : targets)
{
System.out.println(m.reset(s).replaceAll(repl));
}
もちろん、Matcherを再利用することによるパフォーマンス上のメリットは、パターンを再利用することほど優れたものではありません。
String.replaceAll
の実装により、知る必要があるすべてのことがわかります。
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
(そして、ドキュメントは同じことを言っています。)
キャッシングをチェックしていませんが、パターンをコンパイルすることを確実に期待していますonce毎回同じパターンでPattern.compile
を呼び出すよりも静的な参照を保持する方が効率的です。キャッシュがある場合、それは小さな効率の節約になります-ない場合、それは大きなものになる可能性があります。
他の回答はOPのパフォーマンス部分を十分にカバーしていますが、Matcher::replaceAll
とString::replaceAll
の別の違いも、独自のPattern
をコンパイルする理由です。 Pattern
を自分でコンパイルするとき、正規表現の適用方法を変更するフラグなどのオプションがあります。例えば:
Pattern myPattern = Pattern.compile(myRegex, Pattern.CASE_INSENSITIVE);
Matcher
は、Matcher::replaceAll
を呼び出すときに設定したすべてのフラグを適用します。
他にも設定できるフラグがあります。ほとんどの場合、Pattern
およびMatcher
APIには多くのオプションがあり、それが単純なString::replaceAll
を超える主な理由であることを指摘したかっただけです。