1概要

この短い記事では、https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html[

StringBuilder

]とhttps://docsの類似点と相違点について説明します。 Javaでは、.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html[

StringBuffer

]。

簡単に言うと、

StringBuilder



StringBuffer

の代わりとしてJava 1.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()

メソッドを呼び出し、その内容を変更しました。

StringBufferとStringBuilderは可変オブジェクトです。


3違い


StringBuffer

は同期されているためスレッドセーフです。


StringBuilder



StringBuffer

APIと互換性がありますが、同期は保証されません。

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


3.1. パフォーマンス

小さな反復では、パフォーマンスの違いはわずかです。リンク:/java-jvm-warmup[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;
}

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

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

を使用できます。ただし、** 1つの実装を別の実装に置き換える前に、アプリケーションのプロファイルを作成してランタイムパフォーマンスの特性を理解しておくことは、常に

StringBuffer

に対する

StringBuilder

のパフォーマンスの向上が小さすぎるためです。

最後に、いつものように、議論中に使用されたコードはhttps://github.com/eugenp/tutorials/tree/master/java-strings[over on GitHub]にあります。