4

全て、

setLength(0)を使用してStringBufferの内容をクリアするのが理にかなっているのではないかと思っていました。すなわちする方が良いですか:

while (<some condition>)
{
    stringBufferVariable = new StringBuffer(128);
    stringBufferVariable.append(<something>)
                        .append(<more>)
                        ... ;
    Append stringBufferVariable.toString() to a file;
    stringBufferVariable.setLength(0);
}

私の質問:
1>これでも、コンテンツを追加するStringオブジェクトを使用するよりもパフォーマンスが向上しますか?

StringBuffer変数を再初期化すると、パフォーマンスにどのように影響するか、したがって質問にどのように影響するかはよくわかりません。

コメントを入れてください

[編集]:応答に基づいて調べることはこれ以上ないことを理解したので、StringBuilderとの比較に関する2番目の質問を削除しました。

4

6 に答える 6

7

文字列を連結するよりも優れていますか?

あなたが尋ねているなら

stringBufferVariable.append("something")
                    .append("more");
...

通常、と連結するよりもパフォーマンスが向上し+ます。それが、これらのクラスが存在する理由です。charオブジェクトの作成は、配列の値を更新する場合に比べてコストがかかります。

すべてではないにしても、ほとんどのコンパイラが、。などの単純なケースで文字列連結をStringBuilderの使用に変換するようになりましstr = "something" + "more" + "...";た。私が見ることができる唯一のパフォーマンスの違いは、コンパイラには初期サイズを設定する利点がないということです。ベンチマークは、違いが問題になるのに十分かどうかを示します。ただし、を使用+すると、コードが読みやすくなります。

私が読んだことから、コンパイラは、ループで行われる連結を次のようなものの場合、最適化できないようです。

String str = "";
for (int i = 0; i < 10000; i++) {
    str = str + i + ",";
}

したがって、そのような場合でも、StringBuilderを明示的に使用する必要があります。

StringBuilderとStringBuffer

StringBuilderはスレッドセーフではありませんStringBufferが、それ以外は同じです。StringBufferで実行される同期は低速になるため、StringBuilder高速であり、同期が必要でない限り使用する必要があります。

使用する必要がありますsetLengthか?

setLengthあなたの例が現在書かれている方法では、ループを通過するたびに新しいStringBufferを作成しているので、を呼び出しても何も得られないと思います。あなたが本当にすべきことは

StringBuilder sb = new StringBuilder(128);
while (<some condition>) {
    sb.append(<something>)
      .append(<more>)
      ... ;
    // Append stringBufferVariable.toString() to a file;
    sb.setLength(0);
}

これにより、不要なオブジェクトの作成が回避され、この場合、setLengthは内部int変数のみを更新します。

于 2010-10-31T02:43:54.857 に答える
3

私は質問のこの部分に焦点を合わせています。(他の部分は、SOでこれまで何度も質問され、回答されてきました。)

setLength(0)を使用してStringBufferの内容をクリアするのが理にかなっているのではないかと思っていました。

使用しているJavaクラスライブラリによって異なります。sb.toString()一部の古いSunリリースのJavaでは、StringBuffer.toString()は、への呼び出しがバッファーで行われる最後の処理であるという前提で実装されていました。StringBufferの元のバッキング配列は、によって返される文字列の一部になりtoString()ます。その後、StringBufferを使用しようとすると、Stringの内容をコピーして、新しいバッキング配列が作成および初期化されました。したがって、コードが実行しようとしているときにStringBufferを再利用すると、実際にはアプリケーションの速度が低下します。

Java 1.5以降では、これをコーディングするためのより良い方法は次のとおりです。

    bufferedWriter.append(stringBufferVariable);
    stringBufferVariable.setLength(0);

これにより、一時的な文字列を作成することなく、文字列をStringBuilderからファイルバッファに直接コピーする必要があります。StringBuffer宣言がループの外側にある場合、setLength(0)を使用すると、バッファーを再利用できます。

最後に、コードのこの部分がボトルネックである(またはボトルネックになる可能性が高い)という証拠がある場合にのみ、これらすべてについて心配する必要があります。「時期尚早の最適化はすべての悪の根源です」何とか何とか。

于 2010-10-31T02:47:55.590 に答える
1

質問2の場合、StringBuilderはStringBufferよりもパフォーマンスが優れています。StringBufferはスレッドセーフです。つまり、メソッドは同期されます。文字列ビルダーが同期されていません。したがって、使用しているコードを1つのスレッドで実行する場合、同期を行うオーバーヘッドがないため、StringBuilderのパフォーマンスが向上します。

camickrが示唆しているように、詳細については、StringBufferとStringBuilderのAPIを確認してください。

また、あなたはこの記事に興味があるかもしれません:マイクロ最適化劇場の悲しい悲劇

于 2010-10-31T02:32:58.483 に答える
0

1>これでも、コンテンツを追加するStringオブジェクトを使用するよりもパフォーマンスが向上しますか?

はい、新しい文字列オブジェクトを作成し続けるため、文字列の連結は遅くなります。

2>ここでStringBuilderを使用すると、StringBufferよりもパフォーマンスが向上する場合、その理由は何ですか。

StringBuilderやStringBufferのAPIの説明を読みましたか?この発行はそこで扱われます。

StringBuffer変数を再初期化すると、パフォーマンスにどのように影響するか、したがって質問にどのように影響するかはよくわかりません。

さて、テストプログラムを作成します。毎回新しいStringBuffer/Builderを作成するテストを作成します。次に、テストを再実行し、文字を0にリセットしてから、時間を比較します。

于 2010-10-31T02:20:44.737 に答える
0

おそらく私はあなたの質問で何かを誤解しています...各反復の開始時に新しいものを作成しているだけなのに、なぜ下部の長さを0に設定しているのですか?

変数がメソッドのローカル変数であるか、メソッドの外部で宣言されている場合(メソッドの外部にある場合はコードに問題がある可能性があります)、複数のスレッドで使用されないと仮定して、StringBuilderにします。

ループの外側でStringBuilderを宣言する場合、ループに入るたびに新しいStringBuilderを作成する必要はありませんが、ループの最後で長さを0に設定する必要があります。

ループ内でStringBuilderを宣言する場合は、ループの最後で長さを0に設定する必要はありません。

ループの外側で宣言して長さを0に設定する方が速い可能性がありますが、両方を測定し、大きな違いがない場合はループの内側で変数を宣言します。変数の範囲を制限することをお勧めします。

于 2010-10-31T02:46:07.673 に答える
-1

うん!setLength(0)素晴らしいアイデアです!それがその目的です。より迅速な方法は、stringBuffer&を破棄して新しいものを作成することです。その高速で、メモリ効率が良いことについては何も言えません:)

于 2010-10-31T05:41:13.353 に答える