文字列は不変です-つまり、+ =とStringBufferのみを使用しないでください。
-
06-07-2019 - |
質問
文字列は不変です。つまり、作成された文字列は変更できません。
つまり、これは、StringBufferを作成してそれにテキストを追加した場合よりも、+ =を追加した場合により多くのメモリが必要になるということですか?
+ =を使用すると、メモリに保存する必要があるたびに新しい「オブジェクト」を作成しますよね?
解決
はい、毎回+ =で新しいオブジェクトを作成します。ただし、それが常に間違ったことを意味するわけではありません。その値を文字列として使用するか、それを使用して文字列をさらに構築するかによって異なります。
x + y
の結果を文字列として実際に したい場合は、文字列連結を使用することもできます。ただし、(たとえば)ループラウンドして別の文字列や別の文字列などを追加する場合は、結果を文字列として最後にのみ必要とする場合は、StringBuffer / StringBuilderが最適です。実際、ループは実際にStringBuilderが文字列の連結よりも効果的です-5または10の直接連結のパフォーマンスの差は非常に小さくなりますが、何千もの場合はさらに悪化します-基本的にO(N 2 )連結による複雑さvs StringBuilderによるO(N)複雑さ。
Java 5以降では、基本的にStringBuilderを使用する必要があります-同期されていませんが、ほとんどの場合は問題ありません。スレッド間で共有することは非常にまれです。
これに関するすべての記事があります。
他のヒント
経験則は簡単です:
ループで連結を実行している場合は、 + =
ループで連結を実行しているではない場合、 + =
を使用しても問題ありません。 (パフォーマンスが重要なアプリケーションでない限り
Java 5以降では、StringBufferはスレッドセーフであるため、必要でない限り、支払う必要のないオーバーヘッドがあります。 StringBuilderには同じAPIがありますが、スレッドセーフではありません(つまり、単一のスレッドの内部でのみ使用する必要があります)。
はい、大きな文字列を作成する場合は、StringBuilderを使用する方が効率的です。 APIの一部としてStringBuilderまたはStringBufferを渡すことはおそらく価値がありません。これはわかりにくいです。
上記のすべての回答に同意しますが、Javaの実装方法について少し理解するのに役立ちます。 JVMは内部でStringBuffersを使用してString +演算子をコンパイルします( StringBuffer Javadoc ):
文字列バッファは バイナリを実装するコンパイラ 文字列連結演算子+。にとって 例:コード:
x = "a" + 4 + "c"
は次と同等にコンパイルされます:
x = new StringBuffer().append("a").append(4).append("c") .toString()
同様に、 x + =" some new string"
は、 x = x +" some new string"
と同等です。これでどこへ行くのかわかりますか?
多くの文字列連結を行っている場合、StringBufferを使用するとパフォーマンスが向上しますが、単純な文字列連結を2、3個しか行っていない場合、Javaコンパイラはおそらくそれを最適化します。パフォーマンスの違い
はい。文字列は不変です。時々使用する場合は、+ =で問題ありません。 + =操作が集中的な場合は、StringBuilderを使用する必要があります。
ただし、ガベージコレクターは、古い文字列への参照がなくなると、古い文字列を解放します
その通り。ただし、スレッドセーフが問題にならない場合は、StringBuilderを使用する必要があります。
補足:同じバッキングchar []を使用する複数のStringオブジェクトがある場合があります。たとえば、substring()を使用する場合は常に、新しいchar []は作成されず、非常に効率的に使用できます。
さらに、コンパイラーが最適化を行う場合があります。たとえば、次の場合
static final String FOO = "foo";
static final String BAR = "bar";
String getFoobar() {
return FOO + BAR; // no string concatenation at runtime
}
可能であれば、コンパイラが内部でStringBuilderを使用して文字列の連結を最適化しても驚くことはありません。
放棄された文字列でメモリを収集するのはGCに依存していると思います。 したがって、文字列操作で多くの操作を行う場合、文字列ビルダーで+ =を実行すると、確実に高速になります。ただし、ほとんどの場合、これは問題になりません。
はい、それがStringBufferを使用して多くの文字列を連結する必要がある理由です。
また、Java 5以降、ほとんどの場合StringBuilderを好むことに注意してください。単なる非同期のStringBufferのようなものです。
文字列は不変であるというのは正しいので、多くの文字列の連結を行いながらメモリを節約しようとする場合は、+ =ではなくStringBuilderを使用する必要があります。
ただし、気にする必要はありません。プログラムは人間の読者向けに作成されているため、わかりやすく説明できます。最適化することが重要な場合は、最初にプロファイルを作成する必要があります。あなたのプログラムが文字列の活動に対して非常に重くされていない限り、おそらく他のボトルネックがあるでしょう。
いいえ
メモリをそれ以上使用しません。はい、新しいオブジェクトは作成されますが、古いオブジェクトはリサイクルされます。最終的に、使用されるメモリの量は同じです。