StringBuilder versus StringBuffer in Java

1. Overzicht

In dit korte artikel gaan we kijken naar overeenkomsten en verschillen tussen StringBuilder en StringBuffer in Java.

Simpel gezegd, StringBuilder werd geïntroduceerd in Java 1.5 als vervanging voor StringBuffer.

2. Overeenkomsten

Beide StringBuilder en StringBuffer objecten maken die een veranderlijke reeks karakters bevatten. Laten we eens kijken hoe dit werkt en hoe het zich verhoudt tot een onveranderlijk Draad klasse:

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

Ook al lijkt het erop dat we hetzelfde object wijzigen door "Zeker", we maken een nieuwe omdat Draad instanties kunnen niet worden gewijzigd.

Bij gebruik van een van beide StringBuffer of StringBuilder, we kunnen de toevoegen () methode:

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

In dit geval is er geen nieuw object gemaakt. We hebben de toevoegen () methode op sb instantie en de inhoud ervan gewijzigd. StringBuffer en StringBuilder zijn veranderlijke objecten.

3. Verschillen

StringBuffer is gesynchroniseerd en daardoor thread-safe.StringBuilder is compatibel met StringBuffer API maar zonder garantie op synchronisatie.

Omdat het geen threadveilige implementatie is, is het sneller en wordt het aanbevolen om het te gebruiken op plaatsen waar geen thread-veiligheid nodig is.

3.1. Prestatie

Bij kleine iteraties is het prestatieverschil onbeduidend. Laten we een snelle micro-benchmark doen met JMH:

@State (Scope.Benchmark) openbare statische klasse MyState {int iteraties = 1000; String initial = "abc"; String achtervoegsel = "def"; } @Benchmark openbare StringBuffer benchmarkStringBuffer (MyState staat) {StringBuffer stringBuffer = nieuwe StringBuffer (state.initial); voor (int i = 0; i <state.iterations; i ++) {stringBuffer.append (state.suffix); } return stringBuffer; } @Benchmark openbare StringBuilder benchmarkStringBuilder (MyState staat) {StringBuilder stringBuilder = nieuwe StringBuilder (state.initial); voor (int i = 0; i <state.iterations; i ++) {stringBuilder.append (state.suffix); } return stringBuilder; }

We hebben de standaard gebruikt Doorvoer modus - d.w.z. bewerkingen per tijdseenheid (hogere score is beter), wat geeft:

Benchmarkmodus Cnt Score Fouteenheden StringBufferStringBuilder.benchmarkStringBuffer thrpt 200 86169.834 ± 972.477 bewerkingen / s StringBufferStringBuilder.benchmarkStringBuilder thrpt 200 91076.952 ± 2818.028 bewerkingen / s

Als we het aantal iteraties verhogen van 1k naar 1m, krijgen we:

Benchmarkmodus Cnt Score Fouteenheden StringBufferStringBuilder.benchmarkStringBuffer thrpt 200 77,178 ± 0,898 bewerkingen / s StringBufferStringBuilder.benchmarkStringBuilder thrpt 200 85,769 ± 1,966 bewerkingen / s

Laten we echter in gedachten houden dat dit een microbenchmark is, die al dan niet een reële impact kan hebben op de feitelijke, real-world prestaties van een applicatie.

4. Conclusies

Simpel gezegd, de StringBuffer is een threadveilige implementatie en daarom langzamer dan de StringBuilder.

In programma's met één thread kunnen we de StringBuilder. Nog, de prestatiewinst van StringBuilder over- StringBuffer misschien te klein om het overal te vervangen. Het is altijd een goed idee om de applicatie te profileren en de runtime-prestatiekenmerken te begrijpen voordat u enig werk doet om de ene implementatie door een andere te vervangen.

Eindelijk, zoals altijd, is de code die tijdens de discussie is gebruikt, te vinden op GitHub.