Différence entre StringBuilder et StringBuffer


1578

Quelle est la principale différence entre StringBufferet StringBuilder? Y a-t-il des problèmes de performances lors de la décision sur l'un d'entre eux?

Réponses:


1667

StringBufferest synchronisé, StringBuilderne l'est pas.


239
et StringBuilder est conçu comme un remplacement de remplacement de StringBuffer où la synchronisation n'est pas requise
Joel

95
et la synchronisation n'est pratiquement jamais requise. Si quelqu'un veut se synchroniser sur un StringBuilder, il peut simplement entourer le bloc de code entier avec un synchronisé (sb) {} sur l'instance
locka

23
@locka Je dirais que StringBuffer n'est jamais une bonne idée (sauf si vous avez une API qui l'exige) vanillajava.blogspot.de/2013/04/…
Peter Lawrey

8
Le seul endroit que je vois pour un StringBuffer est une console comme une sortie et divers utilitaires de journalisation: de nombreux threads peuvent sortir en conflit. Puisque vous ne voulez pas que 2 sorties soient mélangées ... mais généralement la synchronisation au niveau de StringBuffer est un niveau trop bas, vous voudrez synchroniser au niveau d'un appender comme levelm donc la réponse locka est la meilleure et StringBuffer devrait être déconseillé. Cela permettrait d'économiser du temps de révision du code avec les débutants.
Remi Morin

20
Bon mnémonique pour ceux qui mélangent ces deux - BuFFer était First, plus ancien et donc synchronisé. La nouvelle classe Builder utilise le modèle Builder et est asynchrone.
Datageek

728

StringBuilderest plus rapide que StringBufferparce 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 msfor StringBuffervs 753 msfor for StringBuilder.


10
J'ai changé la chaîne littérale en quelque chose de plus grand: "le renard brun rapide" et j'ai obtenu des résultats plus intéressants. Fondamentalement, ils sont à peu près aussi rapides. J'ai en fait manqué de mémoire, j'ai donc dû en retirer quelques sept. Explication: la synchronisation est optimisée à distance par hotspot. Vous mesurez simplement le temps qu'il faut au hotspot pour le faire (et probablement quelques optimisations supplémentaires).
Jilles van Gurp

7
Vous devez vous échauffer avant. Ce test est injuste pour StringBuffer. En outre, ce serait bien s'il ajoutait quelque chose. En fait, j'ai inversé le test, ajouté une chaîne aléatoire et obtenu le test opposé. Va dire que l'on ne peut pas faire confiance à de simples repères. L'inverse montre que StringBuffer est plus rapide. 5164 pour StringBuilder vs 3699 pour StringBuffer hastebin.com/piwicifami.avrasm
mmm

76
C'est la première fois que je vois --> 0en 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 ?
Raimund Krämer

19
C'est 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.
Sameer Puri

14
D'autres concluent avec des résultats différents: alblue.bandlem.com/2016/04/jmh-stringbuffer-stringbuilder.html . Les benchmarks devraient vraiment être faits avec JMH, pas avec un simple. main()Aussi, votre benchmark est injuste. Il n'y a pas d'échauffement.
Lukas Eder

249

Fondamentalement, les StringBufferméthodes sont synchronisées alors StringBuilderqu'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 Vectoret ArrayList.


1
Aussi avec Hashtableet HashMap.
shmosel

177

Mais nécessaire pour obtenir la différence claire à l'aide d'un exemple?

StringBuffer ou StringBuilder

Utilisez simplement StringBuildersauf si vous essayez vraiment de partager un tampon entre les threads. StringBuilderest le petit frère non synchronisé (moins de surcharge = plus efficace) de la StringBufferclasse synchronisée d'origine .

StringBufferest 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ù.

StringBuilderest venu plus tard. La plupart des utilisations deStringBuffer étaient mono-thread et payaient inutilement le coût de la synchronisation.

Depuis StringBuilderest 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.


14
La première bonne réponse !! Le point est "à moins que vous ne
partagiez

1
réponse très détaillée!
Raúl

81

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.


2
Je veux juste mentionner que les appels de méthode INDIVIDUAL de StringBuffer sont thread-safe. Mais si vous avez plusieurs lignes de code, utilisez un bloc de code synchronisé pour garantir la sécurité des threads, avec un certain verrouillage / moniteur (comme d'habitude ...). Fondamentalement, ne supposez pas seulement que l'utilisation d'une bibliothèque thread-safe garantit immédiatement la sécurité des threads dans VOTRE programme!
Kevin Lee

57

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.


5
Vous avez oublié de faire "t0 = System.currentTimeMillis ();" avant de faire le test StringBuilder. Ainsi, le chiffre affiché pour StringBuilder est en fait le temps qu'il a fallu pour exécuter le test stringbuffer ET stringbuilder. Ajoutez cette ligne et vous verrez que StringBuilder EST plus rapide sur DEUX FOIS.
Gena Batsyan

Notez que ce withString+="some string"+i+" ; ";n'est pas équivalent aux deux autres boucles et n'est donc pas une comparaison équitable.
Dave Jarvis

Exact, corrigé. Les chaînes de pensée sont encore très lentes.
Nicolas Zozol

Pouvez-vous expliquer davantage pourquoi l' augmentation ArrayIndexOutOfBoundsException pour StringBuilder
Alireza Fattahi

Vous devez utiliser JMH pour les tests de performances. Votre indice de référence est vraiment inexact.
Lukas Eder

42

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.


13
La version 1.4 est à la fin de sa durée de vie, il ne semble donc pas intéressant de s'inquiéter de la version antérieure à la version 1.5.
Tom Hawtin - tackline

@ tomHawtin-tackline pas nécessairement - il existe des produits d'entreprise sur la version antérieure à 1.4 que la plupart d'entre nous utilisent quotidiennement. BlackBerry java est également basé sur 1.4 et c'est toujours très actuel.
Richard Le Mesurier

Et CDC et CLDC n'en ont pas StringBuilder.
Jin Kwon

37

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.


23

StringBuffer

  • Synchronisé donc threadsafe
  • Filetage sûr donc lent

StringBuilder

  • Introduit dans Java 5.0
  • Asynchrone donc rapide et efficace
  • L'utilisateur doit explicitement le synchroniser, s'il le souhaite
  • Vous pouvez le remplacer par StringBuffersans autre changement

REMARQUE: seules les opérations simples sont thread-safe, les opérations multiples ne le sont pas. par exemple , si vous appelez appenddeux fois, ou appendet toStringne pas en sécurité.
Peter Lawrey

22

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.


21

StringBuilderet StringBuffersont presque les mêmes. La différence est qu'elle StringBufferest synchronisée et StringBuilderne l'est pas. Bien que StringBuildersoit plus rapide que StringBuffer, la différence de performances est très faible. StringBuilderest 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.


19

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

entrez la description de l'image ici

Ressource: String Vs StringBuffer Vs StringBuilder


StringBuilder est immuable et le type de chaîne est modifiable
Brinda Rathod

Je ne suis pas d'accord pour dire que les chaînes et les StringBuilders sont "rapides" et les StringBuffers sont "très lents". Voir les réponses ci-dessus.
FireCubez

17

String est un immuable.

StringBuffer est un mutable et synchronisé.

StringBuilder est également modifiable, mais ce n'est pas synchronisé.


De plus, StringBuffer verrouille les threads pour accéder à ces données thread-safe, c'est pourquoi le fonctionnement se déroule lentement. StringBuilder ne verrouille pas le thread et il s'exécute de manière multi-threading, c'est pourquoi il est rapide. String - lorsque vous n'avez pas besoin de concaténer une chaîne, c'est une bonne façon, mais lorsque vous en avez besoin, utilisez StringBuilder -> car String crée à chaque fois un nouvel objet en tas, mais StringBuilder retourne le même objet ...
Musa

11

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.


10

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.


6

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");
        }

    }
}

4

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.


4
Les programmes à un seul thread ne sont pas le cas le plus courant en Java, mais StringBuilderles ‍ sont généralement locaux à une méthode, où ils ne sont visibles que par un seul thread.
finnw

4

StringBufferest synchronisé, mais StringBuilderne l'est pas. En conséquence, StringBuilderest plus rapide que StringBuffer.


4

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.


4

StringBuffer:

  • Multi-thread
  • Synchronisé
  • Plus lent que StringBuilder

StringBuilder

  • Single-Thread
  • Non synchronisé
  • Chaîne plus rapide que jamais

2
Plus précisément, String c = a + best é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).
Chop

4

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.


Si vous avez besoin de la sécurité des threads, la meilleure option est d'utiliser StringBuilder car StringBuffer n'est sûr que pour les opérations individuelles. Pour plusieurs opérations, vous avez besoin d'un verrouillage explicite.
Peter Lawrey

4

Meilleure utilisation StringBuildercar il n'est pas synchronisé et offre donc de meilleures performances. StringBuilderest un remplacement sans rendez-vous des plus anciens StringBuffer.


3
@Mark true mais la plupart du temps, StringBu(ff|ild)erc'est une variable locale utilisée uniquement par un seul thread.
gabuzo

1
@MarkMcKenna: Même dans une application multi-thread, il faudrait souvent soit utiliser un verrouillage externe, soit faire un travail supplémentaire pour l'éviter. Par exemple, si deux threads souhaitent chacun ajouter un enregistrement contenant plusieurs chaînes à un constructeur de chaînes, ils devraient agréger les données à ajouter, puis les ajouter en tant qu'unité même si cela aurait été plus rapide - en l'absence de problèmes de thread - pour effectuer simplement une séquence d'opérations d'ajout discrètes.
supercat

3

Puisqu'il StringBufferest synchronisé, il a besoin d'un effort supplémentaire, donc basé sur la perforamance, c'est un peu lent StringBuilder.


3

Il n'y a pas de différences fondamentales entre StringBuilderet StringBuffer, seules quelques différences existent entre elles. Dans StringBufferles 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 StringBuffersont faibles.

En revanche, StringBuildern'est pas synchronisé. Cela signifie qu'à la fois plusieurs threads peuvent fonctionner sur le même StringBuilderobjet en même temps. Cela rend le processus très rapide et donc les performances de StringBuildersont élevées.


3

UNE String est un objet immuable qui signifie que la valeur ne peut pas être modifiée alors qu'il StringBufferest mutable.

Le StringBufferest synchronisé donc thread-safe alors qu'il StringBuilderne l'est pas et ne convient que pour les instances à un seul thread.


3
juste parce que StringBuffer a du code synchronisé, ne signifie pas nécessairement que StringBuffer est threadsafe. Prenons l'exemple suivant: StringBuffer testingBuffer = "stackoverflow"; Maintenant, Thread-1 essaie d'ajouter "1" à testingBuffer, et Thread-2 essaie d'ajouter "2" à testingBuffer. Maintenant, même si la méthode append () est synchronisée, vous ne pouvez pas être sûr que la valeur de testingBuffer sera "stackoverflow12" ou "stackoverflow21". En fait, il est conseillé par Oracle d'utiliser stringbuilder sur stringbuffer. J'espère que cela a aidé :)
Biman Tripathy

2

La principale différence est la StringBuffersynchronisation, mais ce StringBuildern'est pas le cas. Si vous devez utiliser plusieurs threads, StringBuffer est recommandé. Mais, selon la vitesse d'exécution, elle StringBuilderest plus rapide que StringBuffer, car elle n'est pas synchronisée.


4
StringBuffer n'est thread-safe que si vous effectuez une seule opération dessus. Je ne recommanderais pas de l'utiliser dans plusieurs threads car il est très difficile de bien faire les choses.
Peter Lawrey

@PeterLawrey que voulez-vous dire? :-)
Tamad Lang

1
@ b16db0 Je veux dire que la plupart des utilisations de StringBuffer ne sont pas sécurisées pour les threads car elles lui font plusieurs appels sans synchronisation externe, ce qui rend la classe plutôt inutile.
Peter Lawrey

@PeterLawrey ah c'est comme StringBuffer a encore besoin d'un environnement synchronisé.
Tamad Lang du

2

Vérifiez les éléments internes de la méthode d'ajout synchronisé de StringBufferet de la méthode d'ajout non synchronisé de StringBuilder.

StringBuffer :

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

StringBuilder :

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, StringBuffera des frais généraux de performances par rapport à StrinbBuilderdans 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 synchronizedméthodes in append.


1

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");

  }

Execute Me on ideone

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

1
  • StringBuffer est thread-safe mais StringBuilder n'est pas thread-safe.
  • StringBuilder est plus rapide que StringBuffer.
  • StringBuffer est synchronisé tandis que StringBuilder n'est pas synchronisé.

1

StringBuffer est synchronisé et thread-safe, StringBuilder n'est pas synchronisé et plus rapide.


Cette différence a été donnée dans toutes les autres réponses à cette question. Pourriez-vous mettre en évidence quelque chose de nouveau?
Nico Haase
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.