1. 概要

この短い記事では、JavaのStringBuilderStringBufferの類似点と相違点を見ていきます。

簡単に言うと、 StringBuilder は、StringBufferの代わりとしてJava1.5で導入されました。

2. 類似点

StringBuilderとStringBufferはどちらも、文字の可変シーケンスを保持するオブジェクトを作成します。これがどのように機能し、不変のStringクラスとどのように比較されるかを見てみましょう。

String immutable = "abc";
immutable = immutable + "def";

“ def” を追加して同じオブジェクトを変更しているように見えるかもしれませんが、 String インスタンスは変更できないため、新しいオブジェクトを作成しています。

StringBufferまたはStringBuilder、のいずれかを使用する場合、 append()メソッドを使用できます。

StringBuffer sb = new StringBuffer("abc");
sb.append("def");

この場合、新しいオブジェクトは作成されませんでした。 sbインスタンスでappend()メソッドを呼び出し、その内容を変更しました。 StringBufferStringBuilderは可変オブジェクトです。

3. 違い

StringBufferは同期されているため、スレッドセーフです。 StringBuilderStringBuffer APIと互換性がありますが、同期の保証はありません。

スレッドセーフな実装ではないため、より高速であり、スレッドセーフの必要がない場所で使用することをお勧めします。

3.1. パフォーマンス

小さな反復では、パフォーマンスの違いは重要ではありません。 JMHを使用して簡単なマイクロベンチマークを実行してみましょう。

@State(Scope.Benchmark)
public static class MyState {
    int iterations = 1000;
    String initial = "abc";
    String suffix = "def";
}

@Benchmark
public StringBuffer benchmarkStringBuffer(MyState state) {
    StringBuffer stringBuffer = new StringBuffer(state.initial);
    for (int i = 0; i < state.iterations; i++) {
        stringBuffer.append(state.suffix);
    }
    return stringBuffer;
}

@Benchmark
public StringBuilder benchmarkStringBuilder(MyState state) {
    StringBuilder stringBuilder = new StringBuilder(state.initial);
    for (int i = 0; i < state.iterations; i++) {
        stringBuilder.append(state.suffix);
    }
    return stringBuilder;
}

デフォルトのThroughputモードを使用しました–つまり 単位時間あたりの操作(スコアが高いほど良い)。これにより、次のようになります。

Benchmark                                          Mode  Cnt      Score      Error  Units
StringBufferStringBuilder.benchmarkStringBuffer   thrpt  200  86169.834 ±  972.477  ops/s
StringBufferStringBuilder.benchmarkStringBuilder  thrpt  200  91076.952 ± 2818.028  ops/s

反復回数を1kから1mに増やすと、次のようになります。

Benchmark                                          Mode  Cnt   Score   Error  Units
StringBufferStringBuilder.benchmarkStringBuffer   thrpt  200  77.178 ± 0.898  ops/s
StringBufferStringBuilder.benchmarkStringBuilder  thrpt  200  85.769 ± 1.966  ops/s

ただし、これはマイクロベンチマークであり、アプリケーションの実際の実際のパフォーマンスに実際の影響を与える場合と与えない場合があることに注意してください。

4. 結論

簡単に言えば、 StringBuffer はスレッドセーフな実装であるため、StringBuilderよりも低速です。

シングルスレッドプログラムでは、StringBuilderを使用できます。 ただし、 StringBufferに対するStringBuilderのパフォーマンスの向上は小さすぎて、どこでも置き換えることを正当化できない場合があります。 1つの実装を置き換えるためのあらゆる種類の作業を行う前に、アプリケーションのプロファイルを作成し、その実行時のパフォーマンス特性を理解することをお勧めします。他のと。

最後に、いつものように、ディスカッション中に使用されたコードは、GitHubにあります。