StringBuilder et StringBuffer en Java

StringBuilder et StringBuffer en Java

1. Vue d'ensemble

Dans ce court article, nous allons examiner les similitudes et les différences entreStringBuilder etStringBuffer en Java.

En termes simples,StringBuilder a été introduit dans Java 1.5 en remplacement deStringBuffer.

2. Similitudes

LesStringBuilder etStringBuffer créent tous deux des objets contenanta mutable sequence of characters. Voyons comment cela fonctionne et comment cela se compare à une classeString immuable:

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

Même s'il peut sembler que nous modifions le même objet en ajoutant“def”, nous en créons un nouveau car les instances deString ne peuvent pas être modifiées.

Lorsque vous utilisezStringBuffer ouStringBuilder,, nous pouvons utiliser la méthodeappend():

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

Dans ce cas, aucun nouvel objet n'a été créé. Nous avons appelé la méthodeappend() sur l'instancesb et modifié son contenu. StringBuffer etStringBuilder sont des objets mutables.

3. Différences

StringBuffer est synchronisé et donc thread-safe. StringBuilder est compatible avec l'APIStringBuffer mais sans aucune garantie de synchronisation.

Comme il ne s’agit pas d’une implémentation sécurisée pour les threads, elle est plus rapide et il est recommandé de l’utiliser là où la sécurité des threads n’est pas nécessaire.

3.1. Performance

Dans les petites itérations, la différence de performance est insignifiante. Faisons un micro-benchmark rapide avecJMH:

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

Nous avons utilisé le mode par défautThroughput - i.e. opérations par unité de temps (plus le score est élevé, mieux c'est), ce qui donne:

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

Si nous augmentons le nombre d'itérations de 1k à 1m, nous obtenons:

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

Cependant, gardons à l'esprit qu'il s'agit d'un micro-benchmark, qui peut ou non avoir un impact réel sur les performances réelles et réelles d'une application.

4. Conclusions

En termes simples,StringBuffer est une implémentation thread-safe et donc plus lente que lesStringBuilder.

Dans les programmes à un seul thread, nous pouvons prendre desStringBuilder. Pourtant,the performance gain of StringBuilder over StringBuffer may be too small to justify replacing it everywhere. C’est toujours une bonne idée de profiler l’application et de comprendre ses caractéristiques de performances d’exécution avant d’effectuer tout type de travail pour remplacer une implémentation par une autre.

Enfin, comme toujours, le code utilisé lors de la discussion se trouveover on GitHub.