12

文字列は不変です。つまり、一度作成すると変更できません。

では、これは、StringBuffer を作成してそれにテキストを追加した場合よりも、+= を追加した方がより多くのメモリを消費するということでしょうか?

+= を使用すると、メモリに保存する必要があるたびに新しい「オブジェクト」を作成することになりますね。

4

11 に答える 11

25

はい、+= を使用して毎回新しいオブジェクトを作成します。ただし、それが常に間違っているというわけではありません。その値を文字列として使用するか、文字列をさらに構築するために使用するかによって異なります。

実際に文字列としての結果が必要x + yな場合は、文字列連結を使用することもできます。ただし、実際に (たとえば) ループして別の文字列を追加したり、別の文字列を追加したりする場合 - 最後に文字列としての結果のみが必要な場合は、StringBuffer/StringBuilder が適しています。実際、ループは StringBuilder が文字列の連結よりも効果を発揮する場所です - 5 つまたは 10 の直接連結のパフォーマンスの差は非常に小さくなりますが、数千の場合ははるかに悪化します - 基本的に O(N 2 ) の複雑さを得るからですStringBuilder での連結と O(N) の複雑さ。

Java 5 以降では、基本的に StringBuilder を使用する必要があります。非同期ですが、ほとんどの場合問題ありません。スレッド間で共有したいことはほとんどありません。

これらすべてに関する記事があり、役に立つと思います。

于 2009-10-28T07:35:51.763 に答える
7

経験則は簡単です:

連結をループで実行している場合は、使用しないでください+=

連結をループで実行していない場合は、+=単に使用しても問題ありません。(パフォーマンスが重要なアプリケーションでない限り

于 2009-10-28T07:37:23.540 に答える
5

Java 5 以降では、StringBuffer はスレッドセーフであるため、必要でない限り支払うべきではないオーバーヘッドがあります。StringBuilder には同じ API がありますが、スレッド セーフではありません (つまり、単一のスレッドの内部でのみ使用する必要があります)。

はい、大きな文字列を作成する場合は、StringBuilder を使用する方が効率的です。API の一部として StringBuilder または StringBuffer を渡すことはおそらく価値がありません。これは混乱しすぎます。

于 2009-10-28T07:35:15.693 に答える
5

上記のすべての回答に同意しますが、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 を使用するとパフォーマンスが向上しますが、単純な文字列の連結を数回しか行っていない場合は、おそらく Java コンパイラによって最適化されるため、パフォーマンスの違いに気付くことはありません。パフォーマンス

于 2009-10-28T07:47:00.520 に答える
3

はい。文字列は不変です。たまに使うなら += でOK。+= 操作が集中する場合は、StringBuilder を使用する必要があります。

于 2009-10-28T07:34:52.697 に答える
1

丁度。ただし、スレッドセーフが問題にならない場合は、StringBuilder を使用する必要があります。

補足として、同じバッキング char[] を使用する複数の String オブジェクトが存在する可能性があります。

さらに、コンパイラが最適化を行う場合があります。たとえば、

static final String FOO = "foo";
static final String BAR = "bar"; 

String getFoobar() {
  return FOO + BAR; // no string concatenation at runtime
}

コンパイラが可能な限り StringBuilder を内部的に使用して String 連結を最適化しても、私は驚かないでしょう。

于 2009-10-28T07:35:08.843 に答える
1

しかし、ガベージ コレクターは、古い文字列への参照がなくなると、古い文字列を解放してしまいます。

于 2009-10-28T07:35:15.053 に答える
0

いいえ

それ以上のメモリは使用しません。はい、新しいオブジェクトが作成されますが、古いオブジェクトはリサイクルされます。結局、使用されるメモリの量は同じです。

于 2009-10-28T07:49:47.087 に答える
0

放棄された文字列でメモリを収集するのはGCに依存していると思います。したがって、文字列操作の操作が多い場合は、文字列ビルダーで += を実行すると、間違いなく高速になります。しかし、ほとんどの場合、問題にはなりません。

于 2009-10-28T07:35:05.480 に答える
0

はい、そうです。それこそが、StringBuffer を使用して多くの文字列を連結する必要がある理由です。

また、Java 5 以降では、ほとんどの場合 StringBuilder も優先する必要があることに注意してください。これは、非同期の StringBuffer のようなものです。

于 2009-10-28T07:35:11.203 に答える
0

文字列が不変であることは間違いないので、多くの文字列連結を行いながらメモリを節約しようとしている場合は、+= ではなく StringBuilder を使用する必要があります。

ただし、気にならない場合があります。プログラムは人間の読者向けに書かれているため、明確に進めることができます。最適化することが重要な場合は、最初にプロファイリングする必要があります。プログラムが文字列アクティビティに非常に重点を置いていない限り、他のボトルネックが存在する可能性があります。

于 2009-10-28T07:40:34.760 に答える