String.replaceAll()とMatcher.replaceAll()(Regex.Patternから作成されたMatcherオブジェクト上)の間にパフォーマンスの点で既知の違いはありますか?
また、両者の高レベルAPIの違いは何ですか?(不変性、NULLの処理、空の文字列の処理など)
String.replaceAll()とMatcher.replaceAll()(Regex.Patternから作成されたMatcherオブジェクト上)の間にパフォーマンスの点で既知の違いはありますか?
また、両者の高レベルAPIの違いは何ですか?(不変性、NULLの処理、空の文字列の処理など)
のドキュメントによるとString.replaceAll
、メソッドの呼び出しについて次のように述べています。
この形式のメソッドを呼び出すと、
str.replaceAll(regex, repl)
式とまったく同じ結果が得られます。Pattern.compile(regex).matcher(str).replaceAll(repl)
String.replaceAll
したがって、を呼び出してから明示的にaMatcher
を作成するまでのパフォーマンスは同じであることが期待できますPattern
。
編集
コメントで指摘されているように、またはへの1回の呼び出しではパフォーマンスの違いはありませんがreplaceAll
、String
へMatcher
の複数の呼び出しを実行する必要がある場合はreplaceAll
、コンパイルされたものを保持することが有益であると予想されます。Pattern
したがって、比較的高価な正規表現パターンのコンパイルを毎回実行する必要はありません。
ソースコードString.replaceAll()
:
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
最初にパターンをコンパイルする必要があります。短い文字列で同じパターンを使用して何度も実行する場合は、コンパイルした1つのパターンを再利用するとパフォーマンスが大幅に向上します。
Pattern
主な違いは、を生成するために使用されるものを保持すると、使用するMatcher
たびに正規表現を再コンパイルすることを回避できることです。を通過するString
と、このように「キャッシュ」する機能が得られません。
毎回異なる正規表現がある場合は、String
クラスを使用しても問題ありませんreplaceAll
。同じ正規表現を多くの文字列に適用する場合は、正規表現を作成Pattern
して再利用します。
不変性/スレッドセーフ:コンパイルされたパターンは不変ですが、マッチャーは不変ではありません。(Java正規表現スレッドセーフを参照してください)
空の文字列の処理:replaceAllは、空の文字列を適切に処理する必要があります(空の入力文字列パターンとは一致しません)
コーヒーを作るなど:最後に聞いたのですが、String、Pattern、MatcherのいずれにもそのためのAPI機能はありませんでした。
編集:NULLの処理に関しては、StringとPatternのドキュメントには明示的には記載されていませんが、Stringを予期しているため、NullPointerExceptionがスローされると思われます。
の実装は、String.replaceAll
あなたが知る必要があるすべてを教えてくれます:
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
(そして、ドキュメントは同じことを言っています。)
キャッシングをチェックしていませんが、パターンを1回Pattern.compile
コンパイルし、それへの静的参照を保持する方が、毎回同じパターンで呼び出すよりも効率的であると確信しています。キャッシュがある場合は、効率が少し節約されます。キャッシュがない場合は、大きなキャッシュになる可能性があります。
違いは、 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 を再利用することほど大きくはありません。