web-dev-qa-db-ja.com

正規表現をサポートするStringBuilderのreplaceAll?

Java APIといくつかの一般的なサードパーティライブラリを調べましたが、StringBuilderを除いて、String.replaceAllが実行することを実行する適切なメソッドを見つけることができません。

少しの作業でStringBufferに対して実行できることは知っていますが、StringBufferの方が遅いので、この道を進みたくありません。

サードパーティのユーティリティを知っている人はいますか、またはこの機能を実装するための簡単なコードがありますか?

16
Jin Kim

String.replaceAllは、Matcher.replaceAllの便利な方法です。 Matcherは、Javaで正規表現を使用する「実際の」方法であり、より高度なユースケースを可能にします。

さらに、Stringの正規表現メソッドで実行できることはすべて、Matcherの同様のメソッドで実行できます。美しさは、MatchersがStringsだけでなく機能することです。Matchersは任意のCharSequenceStringBuilderStringBufferString、およびCharBufferによって実装されるインターフェイス)に対して取得できます。だからあなたは簡単に行うことができます:

import Java.util.regex.*;

...

StringBuilder sb = new StringBuilder();
sb.append("This works with StringBuffers");
Pattern p = Pattern.compile("\\Buffer\\B");
Matcher m = p.matcher(sb);
System.out.println(m.replaceAll("uilder"));

This works with StringBuildersを出力します。

作業デモ

9
Martin Ender

StringBufferの方が遅いので、この道を進みたくありません。

本当ですが、通常の時期尚早な最適化の警告があり、さらに重要なことに、 最新のJVMはエスケープ分析を使用してStringBuffer/Vector/HashTableロックを削除します 場合によっては、その最適化が行われると、パフォーマンスはおおよそになります同じ。

3
David Ehrmann

正規表現は、変更可能なCharSequenceを内部的に変更しません。正規表現はCharSequenceを解析してStringを返します。ここで、Stringは結果です。 StringBufferは特別な処理があるため例外です-StringBuilderCharSequenceである場合、一致結果で変更する必要があります。

代わりにできること:

// Class
private static final Pattern MY_PATTERN = Pattern.compile("my|regex");

{ // Method
    StringBuilder builder;
    // ...

    Matcher m = MY_PATTERN.matcher(builder);
    builder.replace(0, builder.length(), m.replaceAll("<b>$0</b>"));
}

テストコードのデモを見る!

1
Unihedron

Apache Harmony Matcherソースコード 現在使用されているStringBuilderの代わりにStringBufferで使用するように完全に作り直しているようです。別のパッケージに移動するだけで、多くの依存関係を引きずっていないようです。ファイルの先頭にあるApacheライセンスは、商用プロジェクトでも悪くないかもしれません。

GNU Classpath コードも再利用できますが、ライセンスはそこでより困難になります(変更したバージョンのマッチャーを公開する必要がありますが、コードの残りの部分は公開しない可能性があります)。 OpenJDKプロジェクトで見つけることができる元のSunの実装についても同じです ここ

0