Quelle est la principale différence entre StringBuffer
et StringBuilder
? Y a-t-il des problèmes de performances lors de la décision sur l'un d'entre eux?
Quelle est la principale différence entre StringBuffer
et StringBuilder
? Y a-t-il des problèmes de performances lors de la décision sur l'un d'entre eux?
Réponses:
StringBuffer
est synchronisé, StringBuilder
ne l'est pas.
StringBuilder
est plus rapide que StringBuffer
parce que ce n'est passynchronized
.
Voici un test de référence simple:
public class Main {
public static void main(String[] args) {
int N = 77777777;
long t;
{
StringBuffer sb = new StringBuffer();
t = System.currentTimeMillis();
for (int i = N; i --> 0 ;) {
sb.append("");
}
System.out.println(System.currentTimeMillis() - t);
}
{
StringBuilder sb = new StringBuilder();
t = System.currentTimeMillis();
for (int i = N; i > 0 ; i--) {
sb.append("");
}
System.out.println(System.currentTimeMillis() - t);
}
}
}
Un test donne les nombres de 2241 ms
for StringBuffer
vs 753 ms
for for StringBuilder
.
--> 0
en boucle. Cela m'a pris un moment pour comprendre ce que cela signifie. Est-ce quelque chose qui est réellement utilisé dans la pratique au lieu de la ...; i > 0; i--
syntaxe habituelle ?
i -->
vraiment ennuyeux sur le plan de la syntaxe ... Je pensais que c'était une flèche au début à cause des commentaires sur l'art ASCII.
main()
Aussi, votre benchmark est injuste. Il n'y a pas d'échauffement.
Fondamentalement, les StringBuffer
méthodes sont synchronisées alors StringBuilder
qu'elles ne le sont pas.
Les opérations sont "presque" les mêmes, mais l'utilisation de méthodes synchronisées dans un seul thread est exagérée.
C'est à peu près tout.
Citation de l' API StringBuilder :
Cette classe [StringBuilder] fournit une API compatible avec StringBuffer, mais sans garantie de synchronisation . Cette classe est conçue pour être utilisée en remplacement de StringBuffer dans les endroits où le tampon de chaîne était utilisé par un seul thread (comme c'est généralement le cas). Dans la mesure du possible, il est recommandé d'utiliser cette classe de préférence à StringBuffer car elle sera plus rapide dans la plupart des implémentations.
Il a donc été fait pour le remplacer.
La même chose s'est produite avec Vector
et ArrayList
.
Hashtable
et HashMap
.
Mais nécessaire pour obtenir la différence claire à l'aide d'un exemple?
StringBuffer ou StringBuilder
Utilisez simplement StringBuilder
sauf si vous essayez vraiment de partager un tampon entre les threads. StringBuilder
est le petit frère non synchronisé (moins de surcharge = plus efficace) de la StringBuffer
classe synchronisée d'origine .
StringBuffer
est venu en premier. Sun était soucieux de l'exactitude dans toutes les conditions, ils l'ont donc synchronisé pour le rendre thread-safe au cas où.
StringBuilder
est venu plus tard. La plupart des utilisations deStringBuffer
étaient mono-thread et payaient inutilement le coût de la synchronisation.
Depuis StringBuilder
est un remplacement sans rendez-vous pourStringBuffer
sans la synchronisation, il entre des exemples ne serait pas les différences.
Si vous êtes essayez de partage entre les threads, vous pouvez utiliser StringBuffer
, mais déterminer si la synchronisation de niveau supérieur est nécessaire, par exemple , peut - être au lieu d'utiliser StringBuffer, si vous synchroniser les méthodes qui utilisent le StringBuilder.
Voyons d'abord les similitudes : StringBuilder et StringBuffer sont mutables. Cela signifie que vous pouvez en modifier le contenu, au même endroit.
Différences : StringBuffer est également modifiable et synchronisé. Où StringBuilder est modifiable mais non synchronisé par défaut.
Signification de synchronisé (synchronisation) : Quand quelque chose est synchronisé, plusieurs threads peuvent y accéder et le modifier sans aucun problème ou effet secondaire. StringBuffer est synchronisé, vous pouvez donc l'utiliser avec plusieurs threads sans aucun problème.
Lequel utiliser quand? StringBuilder: lorsque vous avez besoin d'une chaîne, qui peut être modifiable, et qu'un seul thread y accède et la modifie. StringBuffer: lorsque vous avez besoin d'une chaîne, qui peut être modifiable, et que plusieurs threads y accèdent et la modifient.
Remarque : N'utilisez pas StringBuffer inutilement, c'est-à-dire, ne l'utilisez pas si un seul thread le modifie et y accède car il a beaucoup de code de verrouillage et de déverrouillage pour la synchronisation qui prendra inutilement du temps CPU. N'utilisez pas de verrous sauf si cela est nécessaire.
Dans les threads uniques, StringBuffer n'est pas beaucoup plus lent que StringBuilder , grâce aux optimisations JVM. Et en multithreading, vous ne pouvez pas utiliser en toute sécurité un StringBuilder.
Voici mon test (pas une référence, juste un test):
public static void main(String[] args) {
String withString ="";
long t0 = System.currentTimeMillis();
for (int i = 0 ; i < 100000; i++){
withString+="some string";
}
System.out.println("strings:" + (System.currentTimeMillis() - t0));
t0 = System.currentTimeMillis();
StringBuffer buf = new StringBuffer();
for (int i = 0 ; i < 100000; i++){
buf.append("some string");
}
System.out.println("Buffers : "+(System.currentTimeMillis() - t0));
t0 = System.currentTimeMillis();
StringBuilder building = new StringBuilder();
for (int i = 0 ; i < 100000; i++){
building.append("some string");
}
System.out.println("Builder : "+(System.currentTimeMillis() - t0));
}
Résultats:
chaînes: 319740
Tampons: 23
Générateur: 7!
Les constructeurs sont donc plus rapides que les tampons et bien plus rapides que la concaténation de chaînes. Utilisons maintenant un exécuteur pour plusieurs threads:
public class StringsPerf {
public static void main(String[] args) {
ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
//With Buffer
StringBuffer buffer = new StringBuffer();
for (int i = 0 ; i < 10; i++){
executorService.execute(new AppendableRunnable(buffer));
}
shutdownAndAwaitTermination(executorService);
System.out.println(" Thread Buffer : "+ AppendableRunnable.time);
//With Builder
AppendableRunnable.time = 0;
executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
StringBuilder builder = new StringBuilder();
for (int i = 0 ; i < 10; i++){
executorService.execute(new AppendableRunnable(builder));
}
shutdownAndAwaitTermination(executorService);
System.out.println(" Thread Builder: "+ AppendableRunnable.time);
}
static void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // code reduced from Official Javadoc for Executors
try {
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (Exception e) {}
}
}
class AppendableRunnable<T extends Appendable> implements Runnable {
static long time = 0;
T appendable;
public AppendableRunnable(T appendable){
this.appendable = appendable;
}
@Override
public void run(){
long t0 = System.currentTimeMillis();
for (int j = 0 ; j < 10000 ; j++){
try {
appendable.append("some string");
} catch (IOException e) {}
}
time+=(System.currentTimeMillis() - t0);
}
}
Maintenant, les StringBuffers prennent 157 ms pour 100 000 ajouts. Ce n'est pas le même test, mais par rapport aux 37 ms précédents, vous pouvez supposer en toute sécurité que les ajouts de StringBuffers sont plus lents avec une utilisation multithreading . La raison en est que le JIT / hotspot / compiler / quelque chose fait des optimisations lorsqu'il détecte qu'il n'est pas nécessaire de vérifier les verrous.
Mais avec StringBuilder, vous avez java.lang.ArrayIndexOutOfBoundsException , car un thread simultané essaie d'ajouter quelque chose là où il ne devrait pas.
La conclusion est que vous n'avez pas à chasser StringBuffers. Et là où vous avez des fils, réfléchissez à ce qu'ils font avant d'essayer de gagner quelques nanosecondes.
withString+="some string"+i+" ; ";
n'est pas équivalent aux deux autres boucles et n'est donc pas une comparaison équitable.
StringBuilder a été introduit dans Java 1.5, il ne fonctionnera donc pas avec les JVM antérieures.
Depuis les Javadocs :
La classe StringBuilder fournit une API compatible avec StringBuffer, mais sans garantie de synchronisation. Cette classe est conçue pour être utilisée en remplacement de StringBuffer dans les endroits où le tampon de chaîne était utilisé par un seul thread (comme c'est généralement le cas). Dans la mesure du possible, il est recommandé d'utiliser cette classe de préférence à StringBuffer car elle sera plus rapide dans la plupart des implémentations.
StringBuilder
.
Assez bonne question
Voici les différences, j'ai remarqué:
StringBuffer: -
StringBuffer is synchronized
StringBuffer is thread-safe
StringBuffer is slow (try to write a sample program and execute it, it will take more time than StringBuilder)
StringBuilder: -
StringBuilder is not synchronized
StringBuilder is not thread-safe
StringBuilder performance is better than StringBuffer.
Chose banale :-
Les deux ont les mêmes méthodes avec les mêmes signatures. Les deux sont mutables.
StringBuffer
StringBuilder
StringBuffer
sans autre changementappend
deux fois, ou append
et toString
ne pas en sécurité.
StringBuilder n'est pas sûr pour les threads. Le tampon de chaîne est. Plus d'infos ici .
EDIT: En ce qui concerne les performances, après le point d'accès , StringBuilder est le gagnant. Cependant, pour les petites itérations, la différence de performances est négligeable.
StringBuilder
et StringBuffer
sont presque les mêmes. La différence est qu'elle StringBuffer
est synchronisée et StringBuilder
ne l'est pas. Bien que StringBuilder
soit plus rapide que StringBuffer
, la différence de performances est très faible. StringBuilder
est un remplacement de SUN StringBuffer
. Il évite simplement la synchronisation de toutes les méthodes publiques. Plutôt que cela, leur fonctionnalité est la même.
Exemple de bon usage:
Si votre texte va changer et est utilisé par plusieurs threads, il est préférable de l'utiliser StringBuffer
. Si votre texte va changer mais est utilisé par un seul thread, alors utilisez StringBuilder
.
StringBuffer
StringBuffer est mutable signifie que l'on peut changer la valeur de l'objet. L'objet créé via StringBuffer est stocké dans le tas. StringBuffer a les mêmes méthodes que StringBuilder, mais chaque méthode de StringBuffer est synchronisée, c'est-à-dire que StringBuffer est thread-safe.
pour cette raison, il ne permet pas à deux threads d'accéder simultanément à la même méthode. Chaque méthode est accessible par un thread à la fois.
Mais être thread-safe présente également des inconvénients car les performances du StringBuffer sont dues à la propriété thread safe. Ainsi, StringBuilder est plus rapide que StringBuffer lors de l'appel des mêmes méthodes de chaque classe.
La valeur StringBuffer peut être modifiée, cela signifie qu'elle peut être affectée à la nouvelle valeur. De nos jours, c'est une question d'entrevue la plus courante, les différences entre les classes ci-dessus. Le tampon de chaîne peut être converti en chaîne à l'aide de la méthode toString ().
StringBuffer demo1 = new StringBuffer(“Hello”) ;
// The above object stored in heap and its value can be changed .
demo1=new StringBuffer(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuffer
StringBuilder
StringBuilder est identique au StringBuffer, c'est-à-dire qu'il stocke l'objet en tas et qu'il peut également être modifié. La principale différence entre StringBuffer et StringBuilder est que StringBuilder n'est pas non plus thread-safe. StringBuilder est rapide car il n'est pas sûr pour les threads.
StringBuilder demo2= new StringBuilder(“Hello”);
// The above object too is stored in the heap and its value can be modified
demo2=new StringBuilder(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuilder
Ressource: String Vs StringBuffer Vs StringBuilder
String
est un immuable.
StringBuffer
est un mutable et synchronisé.
StringBuilder
est également modifiable, mais ce n'est pas synchronisé.
Le javadoc explique la différence:
Cette classe fournit une API compatible avec StringBuffer, mais sans garantie de synchronisation. Cette classe est conçue pour être utilisée en remplacement de StringBuffer dans les endroits où le tampon de chaîne était utilisé par un seul thread (comme c'est généralement le cas). Dans la mesure du possible, il est recommandé d'utiliser cette classe de préférence à StringBuffer car elle sera plus rapide dans la plupart des implémentations.
StringBuilder
(introduit dans Java 5) est identique à StringBuffer
, sauf que ses méthodes ne sont pas synchronisées. Cela signifie qu'il a de meilleures performances que ce dernier, mais l'inconvénient est qu'il n'est pas thread-safe.
Lisez le tutoriel pour plus de détails.
Un programme simple illustrant la différence entre StringBuffer et StringBuilder:
/**
* Run this program a couple of times. We see that the StringBuilder does not
* give us reliable results because its methods are not thread-safe as compared
* to StringBuffer.
*
* For example, the single append in StringBuffer is thread-safe, i.e.
* only one thread can call append() at any time and would finish writing
* back to memory one at a time. In contrast, the append() in the StringBuilder
* class can be called concurrently by many threads, so the final size of the
* StringBuilder is sometimes less than expected.
*
*/
public class StringBufferVSStringBuilder {
public static void main(String[] args) throws InterruptedException {
int n = 10;
//*************************String Builder Test*******************************//
StringBuilder sb = new StringBuilder();
StringBuilderTest[] builderThreads = new StringBuilderTest[n];
for (int i = 0; i < n; i++) {
builderThreads[i] = new StringBuilderTest(sb);
}
for (int i = 0; i < n; i++) {
builderThreads[i].start();
}
for (int i = 0; i < n; i++) {
builderThreads[i].join();
}
System.out.println("StringBuilderTest: Expected result is 1000; got " + sb.length());
//*************************String Buffer Test*******************************//
StringBuffer sb2 = new StringBuffer();
StringBufferTest[] bufferThreads = new StringBufferTest[n];
for (int i = 0; i < n; i++) {
bufferThreads[i] = new StringBufferTest(sb2);
}
for (int i = 0; i < n; i++) {
bufferThreads[i].start();
}
for (int i = 0; i < n; i++) {
bufferThreads[i].join();
}
System.out.println("StringBufferTest: Expected result is 1000; got " + sb2.length());
}
}
// Every run would attempt to append 100 "A"s to the StringBuilder.
class StringBuilderTest extends Thread {
StringBuilder sb;
public StringBuilderTest (StringBuilder sb) {
this.sb = sb;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
sb.append("A");
}
}
}
//Every run would attempt to append 100 "A"s to the StringBuffer.
class StringBufferTest extends Thread {
StringBuffer sb2;
public StringBufferTest (StringBuffer sb2) {
this.sb2 = sb2;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
sb2.append("A");
}
}
}
StringBuffer est utilisé pour stocker les chaînes de caractères qui seront modifiées (les objets String ne peuvent pas être modifiés). Il se développe automatiquement au besoin. Classes connexes: String, CharSequence.
StringBuilder a été ajouté en Java 5. Il est identique à tous égards à StringBuffer, sauf qu'il n'est pas synchronisé, ce qui signifie que si plusieurs threads y accèdent en même temps, il peut y avoir des problèmes. Pour les programmes à un seul thread, le cas le plus courant, éviter la surcharge de synchronisation rend le StringBuilder très légèrement plus rapide.
StringBuilder
les sont généralement locaux à une méthode, où ils ne sont visibles que par un seul thread.
StringBuffer
est synchronisé, mais StringBuilder
ne l'est pas. En conséquence, StringBuilder
est plus rapide que StringBuffer
.
StringBuffer est mutable. Il peut changer en termes de longueur et de contenu. Les StringBuffers sont thread-safe, ce qui signifie qu'ils ont des méthodes synchronisées pour contrôler l'accès afin qu'un seul thread puisse accéder au code synchronisé d'un objet StringBuffer à la fois. Ainsi, les objets StringBuffer sont généralement sûrs à utiliser dans un environnement multithread où plusieurs threads peuvent essayer d'accéder au même objet StringBuffer en même temps.
StringBuilder La classe StringBuilder est très similaire à StringBuffer, sauf que son accès n'est pas synchronisé de sorte qu'il n'est pas thread-safe. En n'étant pas synchronisé, les performances de StringBuilder peuvent être meilleures que StringBuffer. Ainsi, si vous travaillez dans un environnement à thread unique, l'utilisation de StringBuilder au lieu de StringBuffer peut entraîner une augmentation des performances. Cela est également vrai pour d'autres situations telles qu'une variable locale StringBuilder (c'est-à-dire une variable dans une méthode) où un seul thread accédera à un objet StringBuilder.
StringBuffer:
StringBuilder
String c = a + b
est équivalent à String c = new StringBuilder().append(a).append(b).toString()
, il n'est donc pas plus rapide. Il est seulement que vous créez un nouveau pour chaque chaîne de rendez, alors que vous pourriez avoir qu'un seul ( String d = a + b; d = d + c;
est String d = new StringBuilder().append(a).append(b).toString(); d = new StringBuilder().append(d).append(c).toString();
tout StringBuilder sb = new StringBuilder(); sb.append(a).append(b); sb.append(c); String d = sb.toString();
sauverait un StringBuilder instanciation).
Générateur de chaînes :
int one = 1;
String color = "red";
StringBuilder sb = new StringBuilder();
sb.append("One=").append(one).append(", Color=").append(color).append('\n');
System.out.print(sb);
// Prints "One=1, Colour=red" followed by an ASCII newline.
String-Buffer
StringBuffer sBuffer = new StringBuffer("test");
sBuffer.append(" String Buffer");
System.out.println(sBuffer);
Il est recommandé d'utiliser StringBuilder autant que possible car il est plus rapide que StringBuffer. Cependant, si la sécurité des threads est nécessaire, la meilleure option est les objets StringBuffer.
Meilleure utilisation StringBuilder
car il n'est pas synchronisé et offre donc de meilleures performances. StringBuilder
est un remplacement sans rendez-vous des plus anciens StringBuffer
.
StringBu(ff|ild)er
c'est une variable locale utilisée uniquement par un seul thread.
Puisqu'il StringBuffer
est synchronisé, il a besoin d'un effort supplémentaire, donc basé sur la perforamance, c'est un peu lent StringBuilder
.
Il n'y a pas de différences fondamentales entre StringBuilder
et StringBuffer
, seules quelques différences existent entre elles. Dans StringBuffer
les méthodes sont synchronisées. Cela signifie qu'à la fois un seul thread peut les utiliser. S'il y a plus d'un thread, le deuxième thread devra attendre que le premier se termine et le troisième devra attendre que le premier et le second se terminent, etc. Cela rend le processus très lent et donc les performances dans le cas de StringBuffer
sont faibles.
En revanche, StringBuilder
n'est pas synchronisé. Cela signifie qu'à la fois plusieurs threads peuvent fonctionner sur le même StringBuilder
objet en même temps. Cela rend le processus très rapide et donc les performances de StringBuilder
sont élevées.
UNE String
est un objet immuable qui signifie que la valeur ne peut pas être modifiée alors qu'il StringBuffer
est mutable.
Le StringBuffer
est synchronisé donc thread-safe alors qu'il StringBuilder
ne l'est pas et ne convient que pour les instances à un seul thread.
La principale différence est la StringBuffer
synchronisation, mais ce StringBuilder
n'est pas le cas. Si vous devez utiliser plusieurs threads, StringBuffer est recommandé. Mais, selon la vitesse d'exécution, elle StringBuilder
est plus rapide que StringBuffer
, car elle n'est pas synchronisée.
Vérifiez les éléments internes de la méthode d'ajout synchronisé de StringBuffer
et de la méthode d'ajout non synchronisé de StringBuilder
.
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
public synchronized StringBuffer append(Object obj) {
super.append(String.valueOf(obj));
return this;
}
public synchronized StringBuffer append(String str) {
super.append(str);
return this;
}
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
public StringBuilder append(String str) {
super.append(str);
return this;
}
Étant donné que l'ajout est synchronized
, StringBuffer
a des frais généraux de performances par rapport à StrinbBuilder
dans le scénario multi-thread. Tant que vous ne partagez pas le tampon entre plusieurs threads, utilisez StringBuilder
, ce qui est rapide en raison de l'absence de synchronized
méthodes in append.
Voici le résultat du test de performances pour String vs StringBuffer vs StringBuilder . Enfin, StringBuilder a remporté le test. Voir ci-dessous pour le code de test et le résultat.
Code :
private static void performanceTestStringVsStringbuffereVsStringBuilder() {
// String vs StringBiffer vs StringBuilder performance Test
int loop = 100000;
long start = 0;
// String
String str = null;
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
str += i + "test";
}
System.out.println("String - " + (System.currentTimeMillis() - start) + " ms");
// String buffer
StringBuffer sbuffer = new StringBuffer();
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
sbuffer.append(i).append("test");
}
System.out.println("String Buffer - " + (System.currentTimeMillis() - start) + " ms");
// String builder
start = System.currentTimeMillis();
StringBuilder sbuilder = new StringBuilder();
for (int i = 1; i <= loop; i++) {
sbuffer.append(i).append("test");
}
System.out.println("String Builder - " + (System.currentTimeMillis() - start) + " ms");
}
Résultat :
100000 itération pour ajouter un seul texte
String - 37489 ms
String Buffer - 5 ms
String Builder - 4 ms
10000 itération pour ajouter un seul texte
String - 389 ms
String Buffer - 1 ms
String Builder - 1 ms
StringBuffer est synchronisé et thread-safe, StringBuilder n'est pas synchronisé et plus rapide.