私StringBuilder
は初めて遭遇しましたが、JavaにはすでにString
追加できる非常に強力なクラスがあるので、驚きました。
なぜセカンドString
クラス?
どこでもっと知ることができStringBuilder
ますか?
回答:
String
追加は許可されません。で呼び出す各メソッドString
は、新しいオブジェクトを作成して返します。これは、String
が不変であるためです。内部状態を変更することはできません。
一方、StringBuilder
変更可能です。呼び出すappend(..)
と、新しい文字列オブジェクトを作成するのではなく、内部のchar配列を変更します。
したがって、次のようにする方が効率的です。
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 500; i ++) {
sb.append(i);
}
ではなく、str += i
500個の新しい文字列オブジェクトを作成します。
この例では、ループを使用していることに注意してください。heliosがコメントで指摘しているように、コンパイラーString d = a + b + c
は次のような式を自動的に次のように変換します。
String d = new StringBuilder(a).append(b).append(c).toString();
StringBuffer
に加えてがあることにも注意してくださいStringBuilder
。違いは、前者には同期されたメソッドがあることです。ローカル変数として使用する場合は、を使用してくださいStringBuilder
。複数のスレッドからアクセスされる可能性がある場合は、を使用してくださいStringBuffer
(まれです)
これが理由の具体例です-
int total = 50000;
String s = "";
for (int i = 0; i < total; i++) { s += String.valueOf(i); }
// 4828ms
StringBuilder sb = new StringBuilder();
for (int i = 0; i < total; i++) { sb.append(String.valueOf(i)); }
// 4ms
ご覧のとおり、パフォーマンスの違いは重要です。
s = sb.ToString();
ために、最後にaを実行する時間を含める必要があると思います。そうすれば、少なくとも両方の例で同じことを実行できます(結果はaですstring
)。
Stringクラスは不変ですが、StringBuilderは変更可能です。
String s = "Hello";
s = s + "World";
Stringは不変であるため、上記のコードは2つのオブジェクトを作成します
StringBuilder sb = new StringBuilder("Hello");
sb.append("World");
StringBuilderは不変ではないため、上記のコードでは1つのオブジェクトのみが作成されます。
レッスン:文字列を何度も操作/更新/追加する必要があるときはいつでも、文字列と比較して効率的であるとしてStringBuilderを選択してください。
StringBuilderクラスは変更可能であり、Stringとは異なり、Stringオブジェクトをさらに作成しなくても文字列の内容を変更できます。これにより、文字列を大幅に変更するときにパフォーマンスが向上する可能性があります。StringBufferと呼ばれるStringBuilderに対応するものもあり、これも同期されるため、マルチスレッド環境に最適です。
Stringの最大の問題は、Stringを使用して実行すると、常に新しいオブジェクトが返されることです。
String s1 = "something";
String s2 = "else";
String s3 = s1 + s2; // this is creating a new object.
正確には、すべての文字列を追加するStringBuilderはO(N)であり、文字列の追加はO(N ^ 2)です。ソースコードをチェックすると、これは文字の可変配列を保持することによって内部的に達成されます。StringBuilderは、配列の長さの複製手法を使用して、必要なメモリを2倍にする可能性を犠牲にして、償却されたO(N ^ 2)パフォーマンスを実現します。これを解決するために最後にtrimToSizeを呼び出すことができますが、通常、StringBuilderオブジェクトは一時的にのみ使用されます。最終的な文字列サイズで適切な開始推測を提供することにより、パフォーマンスをさらに向上させることができます。
効率。
文字列を連結するたびに、新しい文字列が作成されます。例えば:
String out = "a" + "b" + "c";
これにより、新しい一時的な文字列が作成され、「a」と「b」がコピーされて「ab」になります。次に、別の新しい一時文字列を作成し、それに「ab」と「c」をコピーして、「abc」にします。次に、この結果はに割り当てられout
ます。
結果は、O(n²)(二次)時間計算量の画家のアルゴリズムであるSchlemielです。
StringBuilder
一方、文字列をインプレースで追加し、必要に応じて出力文字列のサイズを変更できます。
JavaにはString、StringBuffer、StringBuilderがあります。
文字列:その不変
StringBuffer:その可変でスレッドセーフ
StringBuilder:Java 1.5で導入された、変更可能であるがスレッドセーフではない
文字列例:
public class T1 {
public static void main(String[] args){
String s = "Hello";
for (int i=0;i<10;i++) {
s = s+"a";
System.out.println(s);
}
}
}
}
出力:1つの文字列ではなく、10の異なる文字列が作成されます。
Helloa
Helloaa
Helloaaa
Helloaaaa
Helloaaaaa
Helloaaaaaa
Helloaaaaaaa
Helloaaaaaaaa
Helloaaaaaaaaa
Helloaaaaaaaaaa
StringBuilder例:1つのStringBuilderオブジェクトのみが作成されます。
public class T1 {
public static void main(String[] args){
StringBuilder s = new StringBuilder("Hello");
for (int i=0;i<10;i++) {
s.append("a");
System.out.println(s);
}
}
}