web-dev-qa-db-ja.com

String.replaceAllは自分でジョブを実行するよりもかなり遅い

文字列内のトークンの検索と置換を実行する古いコードがあります。

これは、fromtoのペアのマップを受け取り、それらを反復処理し、それらのペアごとにターゲット文字列を反復処理し、indexOf()を使用してfromを検索し、toの値で置き換えます。 StringBufferですべての処理を実行し、最終的にStringを返します。

そのコードを次の行に置き換えました:replaceAll("[,. ]*", "");
そして、いくつかの比較パフォーマンステストを実行しました。
_1,000,000_の反復を比較するとき、私はこれを得ました:

古いコード:1287ms
新しいコード:4605ms

3倍長い!

次に、replaceへの3つの呼び出しに置き換えてみました。
replace(",", "");
replace(".", "");
replace(" ", "");

これにより、次の結果が得られました。

旧コード:1295
新しいコード:3524

2倍長い!

replacereplaceAllが非効率である理由は何ですか?それを速くするために何かできますか?


編集:すべての回答に感謝-主な問題は、確かに_[,. ]*_が私が望んでいたことを実行しなかったことです。これを_[,. ]+_に変更すると、非正規表現ベースのソリューションのパフォーマンスとほぼ同じになります。事前にコンパイルされた正規表現を使用することは役に立ちましたが、限界でした。 (これは私の問題に非常に当てはまる解決策です。

テストコード:
文字列を正規表現に置き換えます:[、。] *
文字列を正規表現に置き換えます:[、。] +
文字列を正規表現に置き換えます:[、。] +および事前コンパイルされたパターン

25
RonK

正規表現を使用すると、someパフォーマンスに影響を与えますが、それほどひどくはありません。

String.replaceAll() を使用すると、呼び出すたびに正規表現がコンパイルされることに注意してください

Pattern オブジェクトを明示的に使用することで、これを回避できます。

Pattern p = Pattern.compile("[,. ]+");

// repeat only the following part:
String output = p.matcher(input).replaceAll("");

また、+ の代わりに *空の文字列の置き換えを回避するため、プロセスを高速化することもできます。

57
Joachim Sauer

replacereplaceAllregexを内部で使用し、ほとんどの場合、深刻な パフォーマンスへの影響 を与えます StringUtils.replace(..) などと比較します。

String.replaceAll()

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

String.replace() 下にあるPattern.compileを使用します。

_public String replace(CharSequence target, CharSequence replacement) {
  return Pattern.compile(target.toString(), Pattern.LITERAL)
         .matcher(this ).replaceAll(
           Matcher.quoteReplacement(replacement.toString()));
}
_

文字列内のすべての部分文字列を置き換える-Javaでより効率的ですか? も参照してください。

8
Johan Sjöberg

コメント欄に書いているように、[. ] *は空の文字列「」に一致します。したがって、文字間のすべての「スペース」はパターンに一致します。多くの ""を ""に置き換えているため、パフォーマンスにのみ記載されています。

これを試してください:

Pattern p = Pattern.compile("[,. ]*");
System.out.println(p.matcher("Hello World").replaceAll("$$$");

それは返します:

H $$$ e $$$ l $$$ o $$$$$$ W $$$ o $$$ r $$$ l $$$ d $$$!$$$

「手動」で行うよりも遅いのも不思議ではありません。あなたは、[. ] +

3
SJuan76