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.