2010-11-26 1 views
11

文字列を取得し、特定の文字セットを他のものに置き換える、ある種のパーサを記述する必要があります。コードは次のようになります。多くの文字列を実行する最速の方法はJavaで置き換えます

noHTMLString = noHTMLString.replaceAll("</p>", "\n"); 
noHTMLString = noHTMLString.replaceAll("<br/>", "\n\n"); 
noHTMLString = noHTMLString.replaceAll("<br />", "\n\n"); 
//here goes A LOT of lines like these ones 

この関数は非常に長く、多くの文字列を置き換えます。ここで問題となるのは、メソッドが何度も呼び出され、アプリケーションのパフォーマンスが低下するため、時間がかかるということです。

私は代替としてのStringBuilderを使用する方法について、ここでいくつかのスレッドを読んだことがあるが、それはでReplaceAllメソッドを欠いており、それはここでは述べていますようStringクラスでDoes string.replaceAll() performance suffer from string immutability?でReplaceAllメソッドが

マッチパターン&マッチャーとMatcher.replaceAllで動作します()はStringBuilderを使用して最終的に返される値 を保存するので、StringBuilderに切り替えると実際に置換を実行する時間が短縮されるかどうかわかりません。

すばやく多くの文字列を置換するための速い方法をご存知ですか?この問題のアドバイスはありますか?

ありがとうございました。

EDIT:htmlテキストのフィールドがいくつかあるレポートを作成する必要があります。各行に対して、これらの文字列内のすべてのhtmlタグと特殊文字を置き換えるメソッドを呼び出しています。完全なレポートでは、すべてのテキストを解析するのに3分以上かかります。問題は、私は非常に頻繁にメソッドを呼び出さなければならないということです。

+0

何が遅くなりますか? - あなたのnoHTMLStringテキストの長さ、またはこの3つのステートメントを非常に頻繁に呼び出すか? – Ralph

+0

私は、htmlテキストでいくつかのフィールドを持つレポートを作成する必要があります。各行に対して、これらの文字列内のすべてのhtmlタグと特殊文字を置き換えるメソッドを呼び出しています。完全なレポートでは、すべてのテキストを解析するのに3分以上かかります。だから私は問題を非常に頻繁に呼び出さなければならないということです。 – Averroes

+0

参照:http://stackoverflow.com/a/1765616/59087 –

答えて

12

StringBufferを気にしたくない場合は、org.apache.commons.lang.StringUtilsが最も高速です。

あなたはこのようにそれを使用することができます:
noHTMLString = StringUtils.replace(noHTMLString, "</p>", "\n");

私はそれが提案されている1 @extraneonに似て私のカスタムStrinBufferソリューションよりも化膿したパフォーマンステストを行いました。

+0

実際、String.classのreplaceAllよりも高速でした。ありがとう。 – Averroes

+0

ベンチマークで[Commons Lang StringUtils.replace performance vs String.replace](http://stackoverflow.com/questions/16228992/commons-lang-stringutils-replace-performance-vs-string-replace)を参照してください。 – Vadzim

+0

複数の文字列を使用する場合は、[StringUtils.replaceEach](https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringUtils.html# [parsing HTML](http://stackoverflow.com/a/1732454/59087)これではなく、replaceEach(java.lang.String、%20java.lang.String []、%20java.lang.String []))方法は良いアイデアです。 –

6

あなたの解析用のHTMLのようですが、ホイールを再発明する代わりに3rd party libraryを使用していますか?

4

Martijnは、自分で解析するのではなく、すぐに使用できるソリューションを使用することに同意します。javax.xmlパッケージのJavaにはたくさんのものが組み込まれています。きちんとした解決策は、XSLT変換を使用して置き換えることです。これは理想的なユースケースのようです。しかし、それは複雑です。

質問に答えるには、regular expression librariesを使用してみましたか?それは、あなたが一致させたいものがたくさんあり、同じもの(\ nか空の文字列)で置き換えているようです。正規表現を使用すると、"<br>|<br/>|<br />"のような式か、<br.*?>"のような巧妙な表現になり、replaceAllを呼び出すことができる正規表現オブジェクトを作成できます。

+2

正規表現でHTMLを解析することはできません:http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-自己完結型タグ –

+1

Adriaan、そうです、HTMLは文脈自由な言語であり、通常の言語ではありません。しかし、正規表現でテキスト置換を行うことができます。これが尋ねられたことです。 – Allanrbo

3

私はここMartijnと完全に同意します。仕事のための適切なツールを選んでください。

ただし、ファイルがHTMLではなく、一部のHTMLトークンしか含まれていない場合は、いくつかの方法でスピードアップできます。

まず、入力のいくつかの量が交換可能な要素が含まれていない場合は、のようなもので始まる考える:

if (!input.contains('<')) { 
    return input; 
} 

第二に、正規表現を考えてみます。

Pattern p = Pattern.compile(your_regex); 

パターンをしないでくださいすべての単一のreplaceAll行に対して、それらを結合しようとします(正規表現にはOR演算子があります)。パターンは正規表現を最適化します。 コンパイル済みパターンを使用し、すべての呼び出しでコンパイルしないでください。かなり高価です。正規表現は、あなたも、いくつかの高速化(しかし、潜在的に読みにくく)交換用のエンジンを自分で実装することができ、複雑にビットがある場合は

StringBuilder result = new StringBuilder(input.length(); 
for (int i=0; i < input.length(); i++) { 
    char c = input.charAt(i); 

    if (c != '<') { 
    continue; 
    } 

    int closePos = input.indexOf('>', i); 
    if (closePos == -1) {// not found 
    result.append(input.substring(i, input.length()); 
    return result.toString(); 
    } 
    i = closePos; 
    String token = input.substring(i, closePos); 
    if (token.equals("p/") { 
    result.append("\\n"); 
    } else if (token.equals(...)) { 
    } else if (...) { 
    } 
} 
return result.toString(); 

これは、いくつかのエラー:)

を有することができる利点は、あなたが持っています入力を1回だけ反復処理します。大きな欠点は、理解するのが簡単ではないということです。新しい状態がどんなものであるべきかを文字ごとに分析するステートマシンを書くこともできます。これは、おそらくより速く、より多くの作業になります。

+1

正規表現でHTMLを解析することはできません:http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags –

+1

@Adriaan Koster:これは私が言ったことではありません。あなたがHTMLを使っているなら、HTMLパーサーを使っています。 HTMLタグを含むプレーンテキスト(HTMLパーサで解析できない)の場合は、難しい方法で試してみてください。 – extraneon

+2

@Adriaan:** WRONG!** [はい、*正規表現でHTMLを解析できます](http://stackoverflow.com/questions/4231382/regular-expression-pattern-not-matching-anywhere-in-string/ 4234491#4234491)。しかし、あなたは[おそらくしたくない](http://stackoverflow.com/questions/4284176/doubt-in-parsing-data-in-perl-where-am-i-going-wrong/4286326#4286326)あなた自身が生成したように、動作するHTMLが制限され、制限されている場合を除きます。さもなければ**完全にHTMLを正規表現**で解析することは可能ですが、あなたは本当に本当に望んでいません。 – tchrist

関連する問題