String と StringBuffer の違いについては誰もがよく理解していると思いますが、これら 2 つのクラスの動作原理についてはまだよくわかっていない人も多いと思われます。今日はこの概念を皆さんのために復習します。その方法 J2SE 5.0 で導入された新しい文字操作クラス、StringBuilder があります。では、この StringBuilder および StringBuffer と、最初に出会った String クラスとの違いは何でしょうか?さまざまな状況でどれを使用する必要がありますか?これらのカテゴリーについて私の意見を共有したいと思います。また、誰もが間違いを犯しているので、それを修正しながら学ぶ良い機会になることを願っています。
簡単に言うと、String 型と StringBuffer 型の主なパフォーマンスの違いは、実際には String が不変オブジェクトであることです (なぜですか? Java の設計者に聞いてください。なぜ String がネイティブ型ではないのか?)。そのため、String 型が変更されるたびに、 , 実際、これは新しい String オブジェクトを生成し、その新しい String オブジェクトを指すポインタを指定することと同じです。したがって、オブジェクトが生成されるたびに内容が頻繁に変更される文字列には String を使用しないことをお勧めします。特にメモリ使用時に、JVM の GC が動作し始め、速度がかなり遅くなります。以下はあまり適切ではない例です。
この場合、for ループが完了した後、メモリ内のオブジェクトが GC によってクリアされていない場合、メモリ内には 20,000 を超える驚くべき数が存在することになります。また、これが多くの人によって使用されるシステムの場合、数はそれほど多くありませんので、ご利用の際はご注意ください。
StringBuffer クラスを使用する場合、結果は毎回異なります。新しいオブジェクトを生成してオブジェクト参照を変更するのではなく、StringBuffer オブジェクト自体に対する操作になります。したがって、一般に、特に文字列オブジェクトが頻繁に変更される場合には、StringBuffer を使用することをお勧めします。一部の特殊なケースでは、String オブジェクトの文字列連結は、実際には JVM によって StringBuffer オブジェクトの連結として解釈されるため、このような場合、String オブジェクトの速度が StringBuffer オブジェクトの速度よりも遅くなることはなく、特に次の文字列オブジェクトはその中で、String の効率は StringBuffer よりもはるかに高速です。
String S1 オブジェクトの生成速度が単純に速すぎることに驚くでしょう。現時点では StringBuffer には速度の点でまったく利点がありません。実際、これは JVM のトリックです。
これから、最初のステップの結論が得られます。ほとんどの場合、StringBuffer > String
そして、StringBuilder はそれらとどう違うのでしょうか?まず簡単に紹介します。StringBuilder は JDK5.0 で新しく追加されたクラスです。StringBuffer との違いは次のとおりです (出典: JavaWorld)。
Java.lang.StringBuffer スレッドセーフな変更可能な文字シーケンス。 String に似た文字列バッファですが、変更できません。文字列バッファは複数のスレッドで安全に使用できます。これらのメソッドは必要に応じて同期できるため、特定のインスタンスに対するすべての操作が、関連する各スレッドによって行われるメソッド呼び出しの順序と一致するシリアル順序で発生するように見えます。
各文字列バッファには一定の容量があります。文字列バッファーに含まれる文字シーケンスの長さがこの容量を超えない限り、新しい内部バッファー配列を割り当てる必要はありません。内部バッファがオーバーフローした場合、この容量は自動的に増加します。 JDK 5.0 以降、シングル スレッドで使用するための同等のクラス StringBuilder がこのクラスに追加されました。 StringBuilder クラスは、すべて同じ操作をサポートしますが、同期を実行しないため高速であるため、通常はこのクラスよりも優先して使用する必要があります。
ただし、複数のスレッドで StringBuilder のインスタンスを使用するのは安全ではありません。このような同期が必要な場合は、StringBuffer を使用することをお勧めします。
そうは言っても、両者の違いは誰でも理解できると思いますので、以下に一般的な導出を行ってみましょう。
ほとんどの場合、StringBuilder > StringBuffer
したがって、この不等式の推移定理によれば、ほとんどの場合、StringBuilder > StringBuffer > String
このような導出結果が得られたので、検証するためにテストを実行してみましょう。
テストコードは次のとおりです。
/** testsb の新しいインスタンスを作成します */
Final static int ttime = 10000;//テストループの数
パブリックtestsb() {
}
public void test(String s){
長い開始 = System.currentTimeMillis();
for(int i=0;i<ttime;i++){
s += "追加";
}
長い間 = System.currentTimeMillis();
System.out.println("操作 "+s.getClass().getName()+" タイプで使用される時間は次のとおりです: " + (over - begin) + " ミリ秒" );
}
public void test(StringBuffer s){
長い開始 = System.currentTimeMillis();
for(int i=0;i<ttime;i++){
s.append("追加");
}
長い間 = System.currentTimeMillis();
System.out.println("操作 "+s.getClass().getName()+" タイプで使用される時間は次のとおりです: " + (over - begin) + " ミリ秒" );
}
public void test(StringBuilder s){
長い開始 = System.currentTimeMillis();
for(int i=0;i<ttime;i++){
s.append("追加");
}
長い間 = System.currentTimeMillis();
System.out.println("操作 "+s.getClass().getName()+" タイプで使用される時間は次のとおりです: " + (over - begin) + " ミリ秒" );
}
// String 上の文字列連結を直接テストします。
public void test2(){
文字列 s2 = "abadf";
長い開始 = System.currentTimeMillis();
for(int i=0;i<ttime;i++){
文字列 s = s2 + s2 + s2 ;
}
長い間 = System.currentTimeMillis();
System.out.println("文字列オブジェクト参照追加型の操作にかかる時間は: " + (over - begin) + " ミリ秒" );
}
public void test3(){
長い開始 = System.currentTimeMillis();
for(int i=0;i<ttime;i++){
文字列 s = "abadf" + "abadf" + "abadf" ;
}
長い間 = System.currentTimeMillis();
System.out.println("操作文字列の追加にかかる時間は次のとおりです: "+ (over - begin) + " ミリ秒" );
}
public static void main(String[] args){
文字列 s1="abc";
StringBuffer sb1 = new StringBuffer("abc");
StringBuilder sb2 = new StringBuilder("abc");
テストsb t = 新しいテストsb();
t.test(s1);
t.test(sb1);
t.test(sb2);
t.test2();
t.test3();
}
}
StringBuffer と StringBuilder の違いがまだわからないようです。ttime を 30000 回追加して確認してください。
java.lang.String 型の操作にかかる時間は 53444 ミリ秒 java.lang.StringBuffer 型の操作にかかる時間は 15 ミリ秒 java.lang.StringBuilder 型の操作にかかる時間は 15 ミリ秒文字列オブジェクト参照加算型の操作に使用 所要時間:31ミリ秒 文字列加算所要時間:0ミリ秒
StringBuffer と StringBuilder のパフォーマンスに大きな違いはありません。これを 100000 に増やして見てみましょう。String 型のテストは大量のデータをテストすることになるため、ここでは追加しません。とても遅いです...
java.lang.StringBuffer 型の操作にかかる時間は 31 ミリ秒 java.lang.StringBuilder 型の操作にかかる時間は 16 ミリ秒
違いがわかりますが、テスト結果の多くは StringBuffer が StringBuilder よりも高速であることを示しています。値を 1000000 に増やして見てみましょう (クラッシュしないはずですよね?)。
java.lang.StringBuffer 型の操作にかかる時間: 265 ミリ秒 java.lang.StringBuilder 型の操作にかかる時間: 219 ミリ秒
違いは少なく、結果は非常に安定しています。もう少し大きくして ttime = 5000000 を見てみましょう。
・・・・・・ スレッド「メイン」の例外 java.lang.OutOfMemoryError: Java ヒープ領域 ・・・・・・
ははは、もうテストしません。基本的に、パフォーマンスは StringBuilder > StringBuffer > String です。