StringBuilder vs StringBuffer i Java

1. Oversikt

I denne korte artikkelen skal vi se på likheter og forskjeller mellom StringBuilder og StringBuffer i Java.

For å si det enkelt, StringBuilder ble introdusert i Java 1.5 som erstatning for StringBuffer.

2. Likheter

Både StringBuilder og StringBuffer lage objekter som inneholder en foranderlig sekvens av tegn. La oss se hvordan dette fungerer, og hvordan det kan sammenlignes med en uforanderlig String klasse:

Uforanderlig streng = "abc"; uforanderlig = uforanderlig + "def";

Selv om det kan se ut som om vi endrer det samme objektet ved å legge det til “Def”, vi lager en ny fordi String forekomster kan ikke endres.

Når du bruker en av dem StringBuffer eller StringBuilder, vi kan bruke legg til () metode:

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

I dette tilfellet ble det ikke opprettet noe nytt objekt. Vi har kalt legg til () metode på sb forekomst og endret innholdet. StringBuffer og StringBuilder er foranderlige gjenstander.

3. Forskjeller

StringBuffer er synkronisert og derfor trådsikker.StringBuilder er kompatibel med StringBuffer API, men uten garanti for synkronisering.

Fordi det ikke er en trådsikker implementering, er det raskere, og det anbefales å bruke det på steder der det ikke er behov for trådsikkerhet.

3.1. Opptreden

I små iterasjoner er ytelsesforskjellen ubetydelig. La oss gjøre et raskt mikrobenchmark med JMH:

@State (Scope.Benchmark) offentlig statisk klasse MyState {int iterasjoner = 1000; Streng initial = "abc"; Strengssuffiks = "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; }

Vi har brukt standard Gjennomstrømning modus - dvs. operasjoner per tidsenhet (høyere poengsum er bedre), noe som gir:

Referansemodus Cnt Score feilenheter StringBufferStringBuilder.benchmarkStringBuffer thrpt 200 86169.834 ± 972.477 ops / s StringBufferStringBuilder.benchmarkStringBuilder thrpt 200 91076.952 ± 2818.028 ops / s

Hvis vi øker antall iterasjoner fra 1k til 1m, får vi:

Referansemodus Cnt Score Feilenheter StringBufferStringBuilder.benchmarkStringBuffer thrpt 200 77.178 ± 0.898 ops / s StringBufferStringBuilder.benchmarkStringBuilder thrpt 200 85.769 ± 1.966 ops / s

La oss imidlertid huske på at dette er en mikro-referanse, som kanskje eller ikke kan ha en reell innvirkning på den faktiske ytelsen til en applikasjon.

4. Konklusjoner

Enkelt sagt, den StringBuffer er en trådsikker implementering og derfor tregere enn StringBuilder.

I programmer med en tråd kan vi ta av StringBuilder. Ennå, ytelsesgevinsten på StringBuilder over StringBuffer kan være for liten til å rettferdiggjøre å erstatte den overalt. Det er alltid en god idé å profilere applikasjonen og forstå dens kjøreegenskaper før du gjør noe arbeid for å erstatte en implementering med en annen.

Til slutt, som alltid, finner du koden som ble brukt under diskusjonen på GitHub.