1681

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

4

32 に答える 32

1747

StringBuffer同期されStringBuilderていません。

于 2008-12-10T04:36:23.110 に答える
750

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

テストの実行により、 forと2241 msforの数値が得られます。StringBuffer753 msStringBuilder

于 2010-05-05T09:15:08.860 に答える
257

基本的に、StringBufferメソッドは同期されますが、そうでStringBuilderはありません。

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

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

StringBuilder APIからの引用:

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

そこで代用するようにしました。

Vectorとについても同じことが起こりましたArrayList

于 2008-12-10T04:37:05.527 に答える
187

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

StringBuffer または StringBuilder

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

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

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

StringBuilderは同期なしのドロップイン置換であるためStringBuffer、どの例にも違いはありません。

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

于 2011-01-25T12:30:54.637 に答える
84

最初に類似点を見てみましょう: StringBuilder と StringBuffer は両方とも変更可能です。つまり、同じ場所でそれらの内容を変更できます。

相違点: StringBuffer は可変であり、同期もされています。StringBuilder は変更可能ですが、デフォルトでは同期されません。

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

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

: StringBuffer を不必要に使用しないでください。つまり、1 つのスレッドのみが変更およびアクセスしている場合は使用しないでください。これには、CPU 時間を不必要に消費する同期用のロックおよびロック解除コードが多数含まれているためです。必要でない限り、ロックを使用しないでください。

于 2013-12-11T07:11:07.613 に答える
58

シングル スレッドでは、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 が発生します。

結論として、StringBuffer を追跡する必要はありません。スレッドがある場合は、数ナノ秒を取得しようとする前に、スレッドが何をしているのかを考えてください。

于 2012-11-15T16:20:46.073 に答える
42

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

Javadocから:

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

于 2008-12-10T04:38:27.240 に答える
37

かなり良い質問

違いは次のとおりです。

文字列バッファ:-

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.

よくあること :-

どちらも同じ署名を持つ同じメソッドを持っています。どちらも可変です。

于 2014-04-11T20:25:07.433 に答える
26

StringBuffer

  • 同期されているためスレッドセーフ
  • スレッドセーフのため遅い

StringBuilder

  • Java 5.0 で導入
  • 非同期であるため高速で効率的
  • ユーザーは、必要に応じて明示的に同期する必要があります
  • StringBuffer他の変更なしで置き換えることができます
于 2008-12-10T05:00:56.773 に答える
23

StringBuilder はスレッドセーフではありません。文字列バッファです。詳細はこちら

編集: パフォーマンスに関しては、ホットスポットが開始された後、StringBuilder が勝者です。ただし、反復回数が少ない場合、パフォーマンスの違いはごくわずかです。

于 2008-12-10T04:41:07.547 に答える
21

StringBuilderStringBufferほとんど同じです。違いは、同期されているのStringBufferと同期されStringBuilderていないということです。StringBuilderはより高速ですが、StringBufferパフォーマンスの違いはごくわずかです。StringBuilderのSUNの代替品ですStringBuffer。すべてのパブリックメソッドからの同期を回避するだけです。それどころか、それらの機能は同じです。

良い使い方の例:

テキストが変更され、複数のスレッドで使用される場合は、を使用することをお勧めしますStringBuffer。テキストが変更されるが、単一のスレッドで使用される場合は、を使用しますStringBuilder

于 2010-12-03T06:38:49.870 に答える
18

String不変です。

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

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

于 2013-03-18T08:12:55.977 に答える
11

javadocは違いを説明しています:

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

于 2011-01-25T12:21:51.247 に答える
10

StringBuilderStringBuffer(Java 5 で導入) は、メソッドが同期されないことを除いて、と同じです。これは、後者よりもパフォーマンスが優れていることを意味しますが、スレッドセーフではないという欠点があります。

詳細については、チュートリアルを参照してください。

于 2011-01-25T12:23:47.527 に答える
6

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

    }
}
于 2014-03-14T18:40:42.357 に答える
4

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

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

于 2014-09-05T10:02:43.060 に答える
4

AStringは不変オブジェクトです。つまり、値は変更できませんがStringBuffer可変です。

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

于 2010-11-17T11:33:16.023 に答える
4

同期さStringBuilderれず、パフォーマンスが向上するため、より適切に使用できます。古い のドロップイン交換です。StringBuilderStringBuffer

于 2011-01-25T12:21:09.947 に答える
4

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

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

于 2009-04-23T13:44:45.263 に答える
4

StringBuffer同期されていますが、同期されていStringBuilderません。その結果、StringBuilderは よりも高速ですStringBuffer

于 2009-12-23T08:42:53.077 に答える
3

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

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

于 2016-05-10T07:57:53.503 に答える
2

主な違いはStringBuffer同期化されていますが、StringBuilderそうではありません。複数のスレッドを使用する必要がある場合は、StringBuffer をお勧めします。ただし、同期化されていないため、実行速度StringBuilderは よりも高速ですStringBuffer

于 2013-11-15T18:05:28.110 に答える
1

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");

  }

ideone で私を処刑する

結果:

1 つのテキストを追加するための 100000 回の反復

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

1 つのテキストを追加するための 10000 回の反復

String - 389 ms
String Buffer - 1 ms
String Builder - 1 ms
于 2018-08-24T07:59:59.117 に答える
1
  • StringBuffer はスレッドセーフですが、StringBuilder はスレッドセーフではありません。
  • StringBuilder は StringBuffer よりも高速です。
  • StringBuffer は同期されますが、StringBuilder は同期されません。
于 2018-11-01T17:41:05.103 に答える
0

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

于 2013-07-01T13:52:16.967 に答える