回答:
StringBuffer
同期されてStringBuilder
いますが、同期されていません。
StringBuilder
それはそうではStringBuffer
ないのでより速いですsynchronized
。
簡単なベンチマークテストは次のとおりです。
public class Main {
public static void main(String[] args) {
int N = 77777777;
long t;
{
StringBuffer sb = new StringBuffer();
t = System.currentTimeMillis();
for (int i = N; i --> 0 ;) {
sb.append("");
}
System.out.println(System.currentTimeMillis() - t);
}
{
StringBuilder sb = new StringBuilder();
t = System.currentTimeMillis();
for (int i = N; i > 0 ; i--) {
sb.append("");
}
System.out.println(System.currentTimeMillis() - t);
}
}
}
テストの実行は、数を与える2241 ms
ためにStringBuffer
対753 ms
のためStringBuilder
。
--> 0
がループで見るのは初めてです。それが何を意味するのか理解するのに少し時間がかかりました。これは通常の...; i > 0; i--
構文の代わりに実際に実際に使用されているものですか?
i -->
、私はそれが理由ASCIIアートについてのコメントの最初にある矢印だと思った...本当に迷惑構文が賢明です。
main()
ます。また、ベンチマークは不公平です。ウォームアップはありません。
基本的に、StringBuffer
メソッドは同期されますが、同期さStringBuilder
れません。
操作は「ほぼ」同じですが、単一のスレッドで同期メソッドを使用するのはやりすぎです。
それはほとんどそれについてです。
StringBuilder APIからの引用:
このクラス[StringBuilder]は、StringBufferと互換性のあるAPIを提供しますが、同期の保証はありません。このクラスは、文字列バッファーが単一のスレッドによって使用されていた場所(一般的なケース)で、StringBufferのドロップイン置換として使用するために設計されています。ほとんどの実装では高速になるため、可能であれば、このクラスをStringBufferよりも優先して使用することをお勧めします。
だからそれを置き換えるために作られました。
同じことがVector
とでも起こりましたArrayList
。
Hashtable
とHashMap
。
しかし、例を使用して明確な違いを得る必要がありますか?
StringBufferまたはStringBuilder
StringBuilder
本当にスレッド間でバッファを共有しようとしているのでない限り、単に使用してください。StringBuilder
同期されていない(オーバーヘッドが少ない=より効率的な)元の同期されたStringBuffer
クラスの弟です。
StringBuffer
最初に来ました。Sunはすべての条件下での正確性に関心を持っていたため、念のためにスレッドセーフにするために同期させました。
StringBuilder
後で来ました。の使用のほとんどStringBuffer
はシングルスレッドであり、同期のコストを不必要に支払っていました。
ためStringBuilder
であるドロップイン交換用StringBuffer
同期せずに、任意の実施例の違いは存在しないであろう。
あなたがいる場合しているスレッド間で共有しようと、あなたが使用することができStringBuffer
、おそらく代わりにStringBufferを使用するなど、より高いレベルの同期が必要であるかどうかを検討し、あなたはStringBuilderのを使用する方法を同期させる必要があります。
最初に類似点を見てみましょう。StringBuilderとStringBufferはどちらも変更可能です。つまり、同じ場所でそれらのコンテンツを変更できます。
相違点:StringBufferは変更可能であり、同期も行われます。StringBuilderは変更可能ですが、デフォルトでは同期されていません。
同期(同期)の意味:何かが同期されると、複数のスレッドがアクセスし、問題や副作用なしに変更できます。StringBufferは同期されるため、問題なく複数のスレッドで使用できます。
どれを使うの? StringBuilder:変更可能な文字列が必要で、1つのスレッドのみがその文字列にアクセスして変更している場合。StringBuffer:変更可能な文字列が必要で、複数のスレッドがその文字列にアクセスして変更している場合。
注:StringBufferを不必要に使用しないでください。つまり、1つのスレッドだけが変更してアクセスしている場合は、使用しないでください。同期のためのロックおよびロック解除コードが多く、CPU時間を不必要に消費します。必要でない限り、ロックを使用しないでください。
シングルスレッドでは、JVMの最適化により、StringBufferはStringBuilderよりも大幅に遅くなることはありません。マルチスレッドでは、StringBuilderを安全に使用することはできません。
これが私のテストです(ベンチマークではなく、単なるテストです):
public static void main(String[] args) {
String withString ="";
long t0 = System.currentTimeMillis();
for (int i = 0 ; i < 100000; i++){
withString+="some string";
}
System.out.println("strings:" + (System.currentTimeMillis() - t0));
t0 = System.currentTimeMillis();
StringBuffer buf = new StringBuffer();
for (int i = 0 ; i < 100000; i++){
buf.append("some string");
}
System.out.println("Buffers : "+(System.currentTimeMillis() - t0));
t0 = System.currentTimeMillis();
StringBuilder building = new StringBuilder();
for (int i = 0 ; i < 100000; i++){
building.append("some string");
}
System.out.println("Builder : "+(System.currentTimeMillis() - t0));
}
結果:
文字列:319740
バッファー:23
ビルダー:7!
そのため、ビルダーはバッファよりも高速で、文字列の連結よりも高速です。次に、Executorを複数のスレッドに使用します。
public class StringsPerf {
public static void main(String[] args) {
ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
//With Buffer
StringBuffer buffer = new StringBuffer();
for (int i = 0 ; i < 10; i++){
executorService.execute(new AppendableRunnable(buffer));
}
shutdownAndAwaitTermination(executorService);
System.out.println(" Thread Buffer : "+ AppendableRunnable.time);
//With Builder
AppendableRunnable.time = 0;
executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
StringBuilder builder = new StringBuilder();
for (int i = 0 ; i < 10; i++){
executorService.execute(new AppendableRunnable(builder));
}
shutdownAndAwaitTermination(executorService);
System.out.println(" Thread Builder: "+ AppendableRunnable.time);
}
static void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // code reduced from Official Javadoc for Executors
try {
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (Exception e) {}
}
}
class AppendableRunnable<T extends Appendable> implements Runnable {
static long time = 0;
T appendable;
public AppendableRunnable(T appendable){
this.appendable = appendable;
}
@Override
public void run(){
long t0 = System.currentTimeMillis();
for (int j = 0 ; j < 10000 ; j++){
try {
appendable.append("some string");
} catch (IOException e) {}
}
time+=(System.currentTimeMillis() - t0);
}
}
StringBuffersが100000回の追加に157ミリ秒かかるようになりました。これは同じテストではありませんが、直前の37ミリ秒と比較すると、マルチスレッドを使用すると、StringBuffersの追加が遅いと安全に想定できます。その理由は、JIT /ホットスポット/コンパイラ/何かがロックをチェックする必要がないことを検出したときに最適化を行うためです。
しかし、StringBuilderを使用すると、並行スレッドが何かを追加してはいけない場所に追加しようとするため、java.lang.ArrayIndexOutOfBoundsExceptionが発生します。
結論として、StringBuffersを追跡する必要はありません。スレッドがある場合は、数ナノ秒を獲得しようとする前に、スレッドが何をしているかを考えます。
withString+="some string"+i+" ; ";
は他の2つのループと同等ではないため、公平な比較ではありません。
StringBuilderはJava 1.5で導入されたため、以前のJVMでは動作しません。
Javadocsから:
StringBuilderクラスは、StringBufferと互換性のあるAPIを提供しますが、同期の保証はありません。このクラスは、文字列バッファが単一のスレッドで使用されていた場所(通常の場合)でStringBufferのドロップイン置換として使用するために設計されています。ほとんどの実装では高速になるため、可能であれば、このクラスをStringBufferよりも優先して使用することをお勧めします。
StringBuilder
。
かなり良い質問
ここに違いがあります、私は気づきました:
StringBuffer:-
StringBuffer is synchronized
StringBuffer is thread-safe
StringBuffer is slow (try to write a sample program and execute it, it will take more time than StringBuilder)
StringBuilder:-
StringBuilder is not synchronized
StringBuilder is not thread-safe
StringBuilder performance is better than StringBuffer.
一般的なこと:-
どちらも同じシグネチャを持つ同じメソッドを持っています。どちらも変更可能です。
StringBuffer
StringBuilder
StringBuffer
他の変更なしで交換できますappend
2回電話した場合やappend
、toString
安全でない場合などです。
StringBuilder
とStringBuffer
ほとんど同じです。違いは、StringBuffer
同期されることと同期されStringBuilder
ないことです。ただし、StringBuilder
より高速ですStringBuffer
、パフォーマンスの違いはごくわずかです。StringBuilder
SUNのの置き換えですStringBuffer
。すべてのパブリックメソッドからの同期を回避するだけです。むしろ、それらの機能は同じです。
良い使い方の例:
テキストが変更され、複数のスレッドで使用される場合は、を使用することをお勧めしますStringBuffer
。テキストが変更されるが、シングルスレッドで使用される場合は、を使用しますStringBuilder
。
StringBuffer
StringBufferは可変なので、オブジェクトの値を変更できます。StringBufferを通じて作成されたオブジェクトは、ヒープに格納されます。StringBufferにはStringBuilderと同じメソッドがありますが、StringBufferの各メソッドは同期されます。つまり、StringBufferはスレッドセーフです。
このため、2つのスレッドが同じメソッドに同時にアクセスすることはできません。各メソッドには、一度に1つのスレッドからアクセスできます。
ただし、スレッドセーフであることにはStringBufferのパフォーマンスが影響するため、スレッドセーフであることにも欠点があります。したがって、各クラスの同じメソッドを呼び出す場合、StringBuilderはStringBufferよりも高速です。
StringBuffer値は変更できます。つまり、新しい値に割り当てることができます。今日、これは最も一般的なインタビューの質問です。上記のクラスの違いです。文字列バッファは、toString()メソッドを使用して文字列に変換できます。
StringBuffer demo1 = new StringBuffer(“Hello”) ;
// The above object stored in heap and its value can be changed .
demo1=new StringBuffer(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuffer
StringBuilder
StringBuilderはStringBufferと同じです。つまり、オブジェクトをヒープに格納し、変更することもできます。StringBufferとStringBuilderの主な違いは、StringBuilderもスレッドセーフではないことです。StringBuilderはスレッドセーフではないため高速です。
StringBuilder demo2= new StringBuilder(“Hello”);
// The above object too is stored in the heap and its value can be modified
demo2=new StringBuilder(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuilder
String
不変です。
StringBuffer
変更可能で同期されています。
StringBuilder
も変更可能ですが、同期されていません。
StringBuilder
(Java 5で導入)はStringBuffer
、メソッドが同期されないことを除いて、と同じです。つまり、後者よりもパフォーマンスが優れていますが、スレッドセーフではないという欠点があります。
読むチュートリアル詳細。
StringBufferとStringBuilderの違いを示す簡単なプログラム:
/**
* Run this program a couple of times. We see that the StringBuilder does not
* give us reliable results because its methods are not thread-safe as compared
* to StringBuffer.
*
* For example, the single append in StringBuffer is thread-safe, i.e.
* only one thread can call append() at any time and would finish writing
* back to memory one at a time. In contrast, the append() in the StringBuilder
* class can be called concurrently by many threads, so the final size of the
* StringBuilder is sometimes less than expected.
*
*/
public class StringBufferVSStringBuilder {
public static void main(String[] args) throws InterruptedException {
int n = 10;
//*************************String Builder Test*******************************//
StringBuilder sb = new StringBuilder();
StringBuilderTest[] builderThreads = new StringBuilderTest[n];
for (int i = 0; i < n; i++) {
builderThreads[i] = new StringBuilderTest(sb);
}
for (int i = 0; i < n; i++) {
builderThreads[i].start();
}
for (int i = 0; i < n; i++) {
builderThreads[i].join();
}
System.out.println("StringBuilderTest: Expected result is 1000; got " + sb.length());
//*************************String Buffer Test*******************************//
StringBuffer sb2 = new StringBuffer();
StringBufferTest[] bufferThreads = new StringBufferTest[n];
for (int i = 0; i < n; i++) {
bufferThreads[i] = new StringBufferTest(sb2);
}
for (int i = 0; i < n; i++) {
bufferThreads[i].start();
}
for (int i = 0; i < n; i++) {
bufferThreads[i].join();
}
System.out.println("StringBufferTest: Expected result is 1000; got " + sb2.length());
}
}
// Every run would attempt to append 100 "A"s to the StringBuilder.
class StringBuilderTest extends Thread {
StringBuilder sb;
public StringBuilderTest (StringBuilder sb) {
this.sb = sb;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
sb.append("A");
}
}
}
//Every run would attempt to append 100 "A"s to the StringBuffer.
class StringBufferTest extends Thread {
StringBuffer sb2;
public StringBufferTest (StringBuffer sb2) {
this.sb2 = sb2;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
sb2.append("A");
}
}
}
StringBufferは、変更される文字列を格納するために使用されます(Stringオブジェクトは変更できません)。必要に応じて自動的に拡張されます。関連クラス:String、CharSequence。
StringBuilderはJava 5で追加されました。StringBufferは、同期されていないことを除いて、すべての点で同じです。つまり、複数のスレッドが同時にアクセスすると問題が発生する可能性があります。最も一般的なシングルスレッドプログラムの場合、同期のオーバーヘッドを回避することで、StringBuilderの速度がわずかに速くなります。
StringBuilder
が、通常、はメソッドに対してローカルであり、1つのスレッドにのみ表示されます。
StringBuffer は変更可能です。長さと内容の点で変わる可能性があります。StringBufferはスレッドセーフです。つまり、アクセスを制御する同期メソッドがあり、一度に1つのスレッドのみがStringBufferオブジェクトの同期コードにアクセスできます。したがって、StringBufferオブジェクトは、複数のスレッドが同じStringBufferオブジェクトに同時にアクセスしようとしている可能性があるマルチスレッド環境で使用しても安全です。
StringBuilder StringBuilderクラスはStringBufferに非常に似ていますが、そのアクセスは同期されないため、スレッドセーフではありません。同期されないことにより、StringBuilderのパフォーマンスはStringBufferよりも優れている場合があります。したがって、シングルスレッド環境で作業している場合、StringBufferの代わりにStringBuilderを使用すると、パフォーマンスが向上する可能性があります。これは、1つのスレッドのみがStringBuilderオブジェクトにアクセスするStringBuilderローカル変数(つまり、メソッド内の変数)などの他の状況にも当てはまります。
StringBuffer:
StringBuilder
String c = a + b
は、と同等であるためString c = new StringBuilder().append(a).append(b).toString()
、高速ではありません。それはあなたが1つしかない可能性がありながら、あなたは、各文字列の逢引のために新しいものを作成することだけです(String d = a + b; d = d + c;
あるString d = new StringBuilder().append(a).append(b).toString(); d = new StringBuilder().append(d).append(c).toString();
一方、StringBuilder sb = new StringBuilder(); sb.append(a).append(b); sb.append(c); String d = sb.toString();
1つのStringBuilderインスタンス化を保存します)。
文字列ビルダー:
int one = 1;
String color = "red";
StringBuilder sb = new StringBuilder();
sb.append("One=").append(one).append(", Color=").append(color).append('\n');
System.out.print(sb);
// Prints "One=1, Colour=red" followed by an ASCII newline.
文字列バッファ
StringBuffer sBuffer = new StringBuffer("test");
sBuffer.append(" String Buffer");
System.out.println(sBuffer);
StringBufferよりも高速であるため、可能な場合は常にStringBuilderを使用することをお勧めします。ただし、スレッドセーフが必要な場合、最良のオプションはStringBufferオブジェクトです。
同期されていないため、より適切に使用できStringBuilder
、パフォーマンスが向上します。あるドロップイン置換古いのは。StringBuilder
StringBuffer
StringBu(ff|ild)er
は単一のスレッドでのみ使用されるローカル変数です。
以来StringBuffer
同期され、それが故にperforamance、遅いよりもそのAビットに基づいて、いくつかの余分な労力を必要としますStringBuilder
。
間には基本的な違いはありませんStringBuilder
とStringBuffer
、ほんのわずかな違いは、それらの間に存在します。ではStringBuffer
メソッド同期されます。これは、一度に1つのスレッドしか操作できないことを意味します。複数のスレッドがある場合、2番目のスレッドは最初のスレッドが終了するのを待たなければならず、3番目のスレッドは最初と2番目のスレッドが終了するのを待たなければなりません。これにより、プロセスが非常に遅くなるため、StringBuffer
は低くなります。
一方、StringBuilder
同期されていません。これは、同時に複数のスレッドが同じStringBuilder
オブジェクトを同時に操作できることを意味します。これによりプロセスが非常に高速になり、パフォーマンスStringBuilder
が高くなります。
AはString
意味不変オブジェクトである値を変更することができないのに対し、StringBuffer
可変です。
StringBuffer
したがって、スレッドセーフをに対し同期されるStringBuilder
単一スレッド・インスタンスには適していないと。
主な違いはされStringBuffer
syncronizedされますが、StringBuilder
あなたが複数のスレッドを使用する必要がnot.If実行速度ごととして、その後のStringBufferは、recommended.ButですStringBuilder
速くよりもStringBuffer
そのはsyncronizedないので、。
同期のappendメソッドの内部チェックStringBuffer
との非同期appendメソッドをStringBuilder
。
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
public synchronized StringBuffer append(Object obj) {
super.append(String.valueOf(obj));
return this;
}
public synchronized StringBuffer append(String str) {
super.append(str);
return this;
}
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
public StringBuilder append(String str) {
super.append(str);
return this;
}
追記であるのでsynchronized
、StringBuffer
と比較して、パフォーマンス・オーバーヘッドを有するStrinbBuilder
シナリオをマルチスレッド。複数のスレッド間でバッファを共有しない限り、を使用してくださいStringBuilder
。これはsynchronized
、appendメソッドがないため高速です。
以下は、String vs StringBuffer vs StringBuilderのパフォーマンステスト結果です。最後に、StringBuilderがテストで優勝しました。テストコードと結果については、以下を参照してください。
コード:
private static void performanceTestStringVsStringbuffereVsStringBuilder() {
// String vs StringBiffer vs StringBuilder performance Test
int loop = 100000;
long start = 0;
// String
String str = null;
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
str += i + "test";
}
System.out.println("String - " + (System.currentTimeMillis() - start) + " ms");
// String buffer
StringBuffer sbuffer = new StringBuffer();
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
sbuffer.append(i).append("test");
}
System.out.println("String Buffer - " + (System.currentTimeMillis() - start) + " ms");
// String builder
start = System.currentTimeMillis();
StringBuilder sbuilder = new StringBuilder();
for (int i = 1; i <= loop; i++) {
sbuffer.append(i).append("test");
}
System.out.println("String Builder - " + (System.currentTimeMillis() - start) + " ms");
}
結果:
1つのテキストを追加するための100000回の反復
String - 37489 ms
String Buffer - 5 ms
String Builder - 4 ms
単一のテキストを追加するための10000回の反復
String - 389 ms
String Buffer - 1 ms
String Builder - 1 ms
StringBufferは同期され、スレッドセーフです。StringBuilderは同期されず、高速です。