遅い文字列の連結過大入力
-
13-09-2019 - |
質問
長々と書きましたn分木を分節木と木の例が紹介される作品。しかしながらプレーする必要がありま店はその直列化可変呼び出します。例えば.
DomTree<String> a = Data.createTreeInstance("very_large_file.xml");
String x = a.toString();
長々と書きました方法で的確かに必要なものの、大型の入力で時間がかか(20分、100MB xmlファイルのいわ方法及びビルのツリーからのxmlファイルが迅速にでき、呼び出しtoString()このようには非常に遅くなります。
@Override
public String toString(){
return printTree(this);
}
public String printTree(AbstractTree<E> tree){
if (tree.isLeaf()){
return tree.getNodeName();
}else{
String tStr = tree.getNodeName() + "(";
int i = 0;
Iterator<AbstractTree<E>> child = tree.getChildren().iterator();
while (i < tree.getChildren().size() - 1){
tStr += printTree(child.next()) + ", ";
i++;
}
tStr += printTree(child.next()) + ")";
return tStr;
}
}
私は推測での、文字列が構築ではなくどのようにツリーをトラバース?あると良い。
更新:以下の例ではSkaffman、以下のコードのoutOfMemoryErrorのための非常に大きな入力します。
@Override
public String toString(){
StringBuilder buffer = new StringBuilder();
printTree(this, buffer);
return buffer.toString();
}
public String printTree(AbstractTree<E> tree, StringBuilder buffer){
if (tree.isLeaf()){
return tree.getNodeName();
}else{
buffer.append(tree.getNodeName());
buffer.append("(");
int i = 0;
Iterator<AbstractTree<E>> child = tree.getChildren().iterator();
while (i < tree.getChildren().size() - 1){
buffer.append(printTree(child.next(), buffer));
buffer.append(", ");
i++;
}
buffer.append(printTree(child.next(), buffer));
buffer.append(")");
return buffer.toString();
}
}
更新:コンビニエンスストアでの現在使用し、Skaffmans例
解決
そのような文字列concatsはpunishingly遅いです。 StringBuilderを使用します。
@Override
public String toString(){
StringBuilder buffer = new StringBuilder();
printTree(this, buffer);
return buffer.toString();
}
public void printTree(AbstractTree<E> tree, StringBuilder buffer){
if (tree.isLeaf()){
buffer.append(tree.getNodeName());
} else {
buffer.append(tree.getNodeName());
buffer.append("(");
int i = 0;
Iterator<AbstractTree<E>> child = tree.getChildren().iterator();
while (i < tree.getChildren().size() - 1){
printTree(child.next(), buffer);
buffer.append(", ");
i++;
}
printTree(child.next(), buffer);
buffer.append(")");
}
}
他のヒント
ループで文字列の連結を使用しないでください。それはスケールしない。
使用のStringBuilder、これは文字列の連結と同様に、新しいオブジェクトのすべての時間がありません..
void print() {
StringBuilder sb = new StringBuilder();
sb.append("hello");
sb.append(" World!");
System.out.println(sb.toString());
}
簡単な連結を使用して、あなたの全体のプロセスを通じてのStringBuilderを渡す(またはそれグローバル作る)していない、StringBuilderのを見ます。
しお話しましょう理由は文字列の連結が遅いので文字列は不変です。このとき書き"+="、新しい文字列を作成します。この方法だくために、自分たちの文字列は、最悪の場合には、O(n2).それがうまくいかない場合+='ed1char同時に、コストの新しい文字列が2 + 3 + 4 + ...+n、O(n2).
利用StringBuilderとしての提案(のが遅くなりthreadsafe StringBuffer).
私は追加、StringBuilderすO(n)の償却時間で作品のようにベクターの裏では可変です。いくために、自分たちの文字列が呼びtoString().
StringBuilder builder = new StringBuilder();
builder.append("blah"); // append more as needed.
String text = builder.toString();
そして追加することでこの問題に入ることになりますが、エラーになります。の熟pythonでは最後に追加することですすべての文字列を連結リストアップ、そして参加します。 "".join(the_list)
.
更新: とをおっしゃったように、連結ではないの源流となっています。については、文字列concatenationsや豪雨で、地滑りや洪水などの場合でも最適化すること!(も最悪の場合イします。ただし、ご列をループしていき、上記の性能を大きく変化することが予想され、数回がアップします。その場合は、上記の分析は北から南東に伸びる形状の為、私が述べられては"最悪の場合、ご負いませんの最適化.(JVMもできない最適な連結、ループなどで外).
場合、プロファイラ 確認 いますが、このボトルネックには文字列連結して選択:
- StringBuilder/StringBuffer(後者は適してスレッド)
- ロープのためのJava:
ロープは、高性能な差し替え用文字列です。のdatastructure,詳細に記述されている"ロープ:代替文字列"は、漸近的には以上のパフォーマンスを両方の文字列およびStringBufferのための共通の文字列の変更など誤動作防止)、追加や削除、メンテナンスをサポートしていません。のような文字列、ロープは、不変で、そのためにも使用に適したマルチスレッドプログラミング
あなたは<のhref = "http://www.j2ee.me/javase/6/docs/api/java/lang/String.html#intern()" のrel = "nofollowをnoreferrer" で見たいと思うかもしれません> String.intern()のメモリの使用を削減する方法として。これは、文字列プールからのインターンの文字列を使用します。あなたは多くの重複文字列を持っている場合、それはより速くかもしれません。インターン文字列の詳細情報ここを