StringBuilder vs StringBuffer in Java

1. Übersicht

In diesem kurzen Artikel werden wir Ähnlichkeiten und Unterschiede zwischen StringBuilder und StringBuffer in Java untersuchen.

Einfach ausgedrückt wurde StringBuilder in Java 1.5 als Ersatz für StringBuffer eingeführt .

2. Ähnlichkeiten

Sowohl StringBuilder als auch StringBuffer erstellen Objekte, die eine veränderbare Folge von Zeichen enthalten. Mal sehen, wie das funktioniert und wie es mit einer unveränderlichen String- 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 String- Instanzen nicht geändert werden können.

Wenn Sie entweder StringBuffer oder StringBuilder verwenden, können Sie die append () -Methode verwenden:

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

In diesem Fall wurde kein neues Objekt erstellt. Wir haben die append () -Methode für die jdn- Instanz aufgerufen und ihren Inhalt geändert. StringBuffer und StringBuilder sind veränderbare Objekte.

3. Unterschiede

StringBuffer ist synchronisiert und daher threadsicher. StringBuilder ist mit der StringBuffer- APIkompatibel,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

Bei kleinen Iterationen ist der Leistungsunterschied unbedeutend. Lassen Sie uns mit JMH einen kurzen Mikro-Benchmark 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 Standard- Durchsatzmodus verwendet - dh Operationen pro Zeiteinheit (höhere Punktzahl ist besser), der Folgendes 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. Schlussfolgerung

Einfach ausgedrückt ist der StringBuffer eine thread-sichere Implementierung und daher langsamer als der StringBuilder .

In Single-Thread-Programmen können wir den StringBuilder nehmen . Doch die Leistungssteigerung von String über String sein kann , zu klein , es überall zu rechtfertigen ersetzen. Es ist 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 ist der während der Diskussion verwendete Code wie immer auf GitHub zu finden.