StringBuilder und StringBuffer in Java

StringBuilder und StringBuffer in Java

1. Überblick

In diesem kurzen Artikel werden wir Ähnlichkeiten und Unterschiede zwischenStringBuilder undStringBuffer in Java untersuchen.

Einfach ausgedrückt wurdeStringBuilder in Java 1.5 als Ersatz fürStringBuffer eingeführt.

2. Ähnlichkeiten

SowohlStringBuilder als auchStringBuffer erstellen Objekte, diea mutable sequence of characters enthalten. Mal sehen, wie das funktioniert und wie es mit einer unveränderlichenString-Klasse verglichen wird:

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

Auch wenn es so aussieht, als würden wir dasselbe Objekt durch Anhängen von“def” ändern, erstellen wir ein neues, da die Instanzen vonStringnicht geändert werden können.

Wenn Sie entwederStringBuffer oderStringBuilder, verwenden, können Sie die Methodeappend() verwenden:

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

In diesem Fall wurde kein neues Objekt erstellt. Wir haben die Methodeappend()für die Instanz vonsbaufgerufen und ihren Inhalt geändert. StringBuffer undStringBuilder sind veränderbare Objekte.

3. Unterschiede

StringBuffer ist synchronisiert und daher threadsicher. StringBuilder ist mit der API vonStringBufferkompatibel, jedoch ohne Garantie für die Synchronisation.

Da es sich nicht um eine thread-sichere Implementierung handelt, ist sie schneller und es wird empfohlen, sie an Orten zu verwenden, an denen keine Thread-Sicherheit erforderlich ist.

3.1. Performance

In kleinen Iterationen ist der Leistungsunterschied unbedeutend. Lassen Sie uns einen schnellen Mikro-Benchmark mitJMH durchführen:

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

Wir haben den StandardmodusThroughput verwendet - d. H. Operationen pro Zeiteinheit (höhere Punktzahl ist besser), was ergibt:

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

Wenn wir die Anzahl der Iterationen von 1k auf 1m erhöhen, erhalten wir:

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

Beachten Sie jedoch, dass dies ein Mikro-Benchmark ist, der einen tatsächlichen Einfluss auf die tatsächliche Leistung einer Anwendung haben kann oder nicht.

4. Schlussfolgerungen

Einfach ausgedrückt istStringBuffer eine thread-sichere Implementierung und daher langsamer alsStringBuilder.

In Single-Thread-Programmen können wir dieStringBuilder nehmen. the performance gain of StringBuilder over StringBuffer may be too small to justify replacing it everywhere.Es ist jedoch immer eine gute Idee, die Anwendung zu profilieren und ihre Laufzeitleistungsmerkmale zu verstehen, bevor Sie Arbeiten ausführen, um eine Implementierung durch eine andere zu ersetzen.

Schließlich kann wie immer der während der Diskussion verwendete Codeover on GitHub gefunden werden.