web-dev-qa-db-ja.com

StringBuilderとStringBufferの違い

StringBufferStringBuilderの主な違いは何ですか?これらのいずれかを決定する際にパフォーマンス上の問題はありますか?

1450
blacktiger

StringBuffer は同期されますが、 StringBuilder は同期されません。

1557
sblundy

StringBuilderStringBufferではないので 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);
        }
    }
}

テスト実行StringBufferに対する2241 msStringBuilderに対する753 msの数を与えます。

700

基本的にStringBufferメソッドは同期されますがStringBuilderは同期されません。

操作は「ほぼ」同じですが、単一スレッドで同期メソッドを使用するのはやり過ぎです。

それはそれについてほとんどです。

からの引用符 - StringBuilder API

このクラス[StringBuilder]はStringBuffer、と互換性のあるAPIを提供しますが、同期の保証はありません。このクラスは、文字列バッファがシングルスレッドによって使用されていた場所でのStringBufferのドロップイン置換として使用するために設計されています(一般的な場合)。可能であれば、このクラスはStringBufferよりもとして優先的に使用することをお勧めします。

それでそれを代用するようにされました。

VectorArrayListでも同じことが起こりました。

234
OscarRyz

しかし、例の助けを借りて明確な違いを得る必要がありますか?

StringBufferまたはStringBuilder

単にスレッド間でバッファを共有しようとしている場合を除き、単にStringBuilderを使用します。 StringBuilderは、元の同期StringBufferクラスの同期されていない(オーバーヘッドが少ない=より効率的な)弟です。

StringBufferが最初に来ました。 Sunはすべての条件下での正確性に関心があったため、万が一に備えてスレッドセーフにするために同期させました。

StringBuilderは後で来ました。 StringBufferの使用のほとんどはシングルスレッドであり、同期のコストを不必要に支払っています。

StringBuilderdrop-in replacementであるため、StringBufferは同期の場合、どの例にも違いはありません。

areスレッド間で共有しようとしている場合、StringBufferを使用できますが、より高いレベルの同期が必要かどうかを検討してください。おそらくStringBufferを使用する代わりに、StringBuilderを使用するメソッドを同期する必要があります。

161
Bert F

最初に 類似点を見てみましょう :StringBuilderとStringBufferはどちらも可変です。つまり、同じ場所でそれらのコンテンツを変更できます。

違い :StringBufferは可変で同期もされています。 StringBuilderは変更可能だがデフォルトでは同期されない。

同期された(同期)の意味 :何らかのことが同期されると、複数のスレッドがアクセスしたり、問題や副作用なしにそれを変更したりすることができます。 StringBufferは同期化されているので、問題なく複数のスレッドで使用できます。

いつ使うの? StringBuilder:変更可能な文字列が必要で、それにアクセスして変更しているスレッドが1つだけの場合。 StringBuffer:変更可能な文字列が必要で、複数のスレッドがそれにアクセスして変更している場合。

:StringBufferを不必要に使用しないでください。つまり、1つのスレッドだけがそれを変更およびアクセスしている場合は使用しないでください。必要な場合以外はロックを使用しないでください。

75
user1923551

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!

つまり、BuilderはBuffersよりも速く、WAYはストリング連結よりも高速です。それではマルチスレッドに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 msを使用します。これは同じテストではありませんが、前の37ミリ秒と比較すると、安全にStringBuffersのアペンドはマルチスレッドの使用では遅いと見なすことができます。その理由は、JIT/hotspot/compiler/somethingが no ロックをチェックする必要があることを検出したときに最適化を行うからです。

ただし、StringBuilderでは、Java.lang.ArrayIndexOutOfBoundsExceptionがあります _は、並行スレッドが本来あるべき場所に追加しようとしているためです。

結論としては、StringBuffersを追う必要はないということです。そして、あなたがスレッドを持っているところで、数ナノ秒を得ることを試みる前に、それらが何をしているかについて考えてください。

46
Nicolas Zozol

StringBuilderはJava 1.5で導入されたため、以前のJVMでは動作しません。

Javadocs :から:

StringBuilderクラスはStringBufferと互換性のあるAPIを提供しますが、同期の保証はありません。このクラスは、文字列バッファがシングルスレッドによって使用されていた場所でのStringBufferのドロップイン置換として使用するために設計されています(一般的な場合)。可能であれば、このクラスはStringBufferよりも優先して使用することをお勧めします。ほとんどの実装では高速になるからです。

39
Marc Novakowski

かなり良い質問

ここに違いがあります、私は気づいています:

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.

一般的なこと: -

どちらも同じシグネチャを持つ同じメソッドを持っています。どちらも変更可能です。

34

StringBuilderはスレッドセーフではありません。文字列バッファはです。より多くの情報 ここ

編集:パフォーマンスに関しては、 hotspot が開始された後、StringBuilderが勝者です。ただし、小さな反復では、パフォーマンスの違いはごくわずかです。

21
Learning

StringBuilderStringBufferはほぼ同じです。違いは、StringBufferは同期され、StringBuilderは同期されないということです。 StringBuilderStringBufferより速いですが、パフォーマンスの違いはほとんどありません。 StringBuilderは、SunがStringBufferを置き換えたものです。それだけですべてのパブリックメソッドからの同期を回避します。それよりもむしろ、それらの機能は同じです。

良い使い方の例:

あなたのテキストが変更され、複数のスレッドによって使用される場合は、StringBufferを使用することをお勧めします。あなたのテキストを変更しようとしているが単一のスレッドによって使用されている場合は、StringBuilderを使用してください。

20
subodh ray

StringBuffer

  • 同期化されているのでスレッドセーフ
  • スレッドセーフなので遅い
  • -

StringBuilder

  • Java 5.0で導入された
  • 非同期で高速で効率的
  • 必要に応じて、ユーザーは明示的に同期する必要があります。
  • 他の変更なしにStringBuilderに置き換えられます
19
JRomio

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

enter image description here

リソース: String Vs StringBuffer Vs StringBuilder

17
Virtual

Stringは不変です。

StringBufferは可変で同期されています。

StringBuilderも可変ですが、同期はされていません。

15
sudhakar

javadoc は違いを説明します。

このクラスはStringBufferと互換性のあるAPIを提供しますが、同期の保証はありません。このクラスは、文字列バッファがシングルスレッドによって使用されていた場所でのStringBufferのドロップイン置換として使用するために設計されています(一般的な場合)。可能であれば、このクラスはStringBufferよりも優先して使用することをお勧めします。ほとんどの実装では高速になるからです。

11
skaffman

(Java 5で導入された)StringBuilderは、そのメソッドが同期されていないことを除いて、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");
        }

    }
}
5
Kevin Lee

StringBuffer:

  • マルチスレッド
  • 同期しています
  • StringBuilderより遅い

StringBuilder

  • シングルスレッド
  • 非同期
  • これまで以上に速い
4
Asif Mushtaq

文字列ビルダー

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オブジェクトが最善の選択肢です。

4
Avinash

StringBuilderは同期されていないのでパフォーマンスが向上しているので、StringBuilderを使用してください。 StringBuilderは、古いStringBufferの代わりになるドロップインです。

4
Niclas

StringBuffer は可変です。それは長さと内容の点で変わることがあります。 StringBuffersはスレッドセーフです。つまり、アクセスを制御する同期メソッドがあるため、一度に1つのスレッドだけがStringBufferオブジェクトの同期コードにアクセスできます。したがって、StringBufferオブジェクトは一般に、複数のスレッドが同時に同じStringBufferオブジェクトにアクセスしようとしている可能性があるマルチスレッド環境で安全に使用できます。

StringBuilder StringBuilderクラスはStringBufferとよく似ていますが、アクセスが同期されていないためスレッドセーフではありません。同期されないことで、StringBuilderのパフォーマンスはStringBufferよりも優れたものになります。したがって、シングルスレッド環境で作業している場合は、StringBufferの代わりにStringBuilderを使用するとパフォーマンスが向上する可能性があります。これは、StringBuilderオブジェクトにアクセスするスレッドが1つだけになるStringBuilderローカル変数(つまり、メソッド内の変数)などの他の状況にも当てはまります。

4
Android Genius

StringBufferは同期されていますが、StringBuilderは同期されていません。その結果、StringBuilderStringBufferより速くなります。

4
Ahmad adawi

StringBufferは同期化されているので、余分な労力を必要とします。したがって、パフォーマンスに基づいて、StringBuilderよりも少し遅くなります。

3

StringBuilderとStringBufferの間には基本的な違いはありませんが、違いがいくつかあります。 StringBufferでは、メソッドは同期されています。これは、一度に1つのスレッドしか操作できないことを意味します。複数のスレッドがある場合、2番目のスレッドは最初のスレッドが終了するのを待たなければならず、3番目のスレッドは1番目と2番目のスレッドが終了するのを待つ必要があります。これにより処理が非常に遅くなり、したがってStringBufferの場合のパフォーマンスが低下します。

一方、StringBuilderは非同期です。これは、一度に複数のスレッドが同じStrinBuilderオブジェクトを同時に操作できることを意味します。これはプロセスを非常に速くするので、StringBuilderのパフォーマンスは高いです。

3
Pratik Paul

StringBufferは、変更される文字列を格納するために使用されます(Stringオブジェクトは変更できません)。必要に応じて自動的に拡張します。関連クラス:String、CharSequence。

StringBuilderはJava 5で追加されました。同期されない点を除いて、StringBufferとすべての点で同じです。つまり、複数のスレッドが同時にアクセスした場合、問題が発生する可能性があります。シングルスレッドプログラムの場合、最も一般的なケースでは、同期のオーバーヘッドを回避することでStringBuilderが少し速くなります。

3
abhishek pathak

主な違いはStringBufferは同期されていますがStringBuilderは同期されていないということです。複数のスレッドを使用する必要がある場合はStringBufferをお勧めします。実行速度の観点からStringBuilderStringBufferより高速です。

Stringは不変のオブジェクトなので、StringBufferが変更可能な場合は値を変更できません。

StringBuilderはシングルスレッドのインスタンスには適していないため、StringBufferは同期化されているためスレッドセーフです。

2
Ketan Patel

StringBufferの同期追加メソッドとStringBuilderの非同期追加メソッドの内部を確認してください。

StringBuffer

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;
}

StringBuilder

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;
}

Appendはsynchronizedなので、マルチスレッドのシナリオではStringBufferStrinbBuilderと比較してパフォーマンスのオーバーヘッドがあります。複数のスレッド間でバッファを共有していない限り、StringBuilderを使用します。これは、appendメソッドにsynchronizedがないため高速です。

2
Ravindra babu
  • StringBufferはスレッドセーフですが、StringBuilderはスレッドセーフではありません。
  • StringBuilderはStringBufferより速いです。
  • StringBufferは同期されますが、StringBuilderは同期されません。
1
Praveen Kishor

これは、 String vs StringBuffer対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");

  }

ideoneで自分を実行

結果

単一のテキストを追加するための10万回の繰り返し

String - 37489 ms
String Buffer - 5 ms
String Builder - 4 ms

単一のテキストを追加するための10000回の繰り返し

String - 389 ms
String Buffer - 1 ms
String Builder - 1 ms
1

StringBufferは同期され、スレッドセーフです。StringBuilderは同期されておらず、高速です。

0
G.Brown

StringBufferに存在するすべてのメソッドはSynchronizedです。したがって、StringBufferオブジェクトを操作できるのは一度に1つのスレッドだけです。この問題を解決するために、スレッドの待機時間が増え、パフォーマンスの問題が発生します。Sun Peopleは、バージョン1.5でStringBuilderを導入しました。

0
Srinivas