web-dev-qa-db-fra.com

Différence entre StringBuilder et StringBuffer

Quelle est la principale différence entre StringBuffer et StringBuilder? Existe-t-il des problèmes de performances lors de la décision?

1478
blacktiger

StringBuffer est synchronisé, StringBuilder n'est pas.

1587
sblundy

StringBuilder est plus rapide que StringBuffer car ce n'est pas synchronized.

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

A test donne les numéros de 2241 ms pour StringBuffer et 753 ms pour StringBuilder.

709

Fondamentalement, les méthodes StringBuffer sont synchronisées alors que StringBuilder ne le sont pas.

Les opérations sont "presque" identiques, mais l'utilisation de méthodes synchronisées dans un seul thread est excessive.

C'est à peu près à ce sujet.

Citation de 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 comme remplacement immédiat 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 mises en œuvre .

Donc, il a été fait pour le remplacer.

La même chose s'est produite avec Vector et ArrayList.

236
OscarRyz

Mais avez-vous besoin de voir clairement la différence à l'aide d'un exemple?

StringBuffer ou StringBuilder

tilisez simplement StringBuilder sauf si vous essayez réellement de partager un tampon entre les threads. StringBuilder est le frère cadet non synchronisé (moins de charge = plus efficace) la classe StringBuffer synchronisée d'origine.

StringBuffer est arrivé 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 de StringBuffer étaient mono-thread et payaient inutilement le coût de la synchronisation.

Puisque StringBuilder est un remplacement ) pour StringBuffer sans synchronisation, il n'y aurait pas être des différences entre des exemples.

Si vous essayez de partager des threads, vous pouvez utiliser StringBuffer, mais déterminez si une synchronisation de niveau supérieur est nécessaire, par exemple. peut-être au lieu d'utiliser StringBuffer, devriez-vous synchroniser les méthodes qui utilisent StringBuilder.

161
Bert F

Voyons d’abord les similarités: StringBuilder et StringBuffer sont mutables. Cela signifie que vous pouvez en modifier le contenu, au même endroit.

Différences: StringBuffer est modifiable et synchronisé. StringBuilder est mutable, mais pas synchronisé par défaut.

Signification de synchronized (synchronisation): Quand quelque chose est synchronisé, plusieurs threads peuvent y accéder et le modifier sans aucun problème ni 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 pouvant être modifiable, et qu'un seul thread y accède et la modifie. StringBuffer: Lorsque vous avez besoin d'une chaîne, pouvant être modifiable, et que plusieurs threads y accèdent et la modifient.

Note: N'utilisez pas StringBuffer inutilement, c'est-à-dire, ne l'utilisez pas si un seul thread le modifie et y accède car il contient beaucoup de code de verrouillage et de déverrouillage pour la synchronisation, ce qui prendra inutilement du temps CPU . N'utilisez pas de cadenas sauf si cela est requis.

76
user1923551

Dans les threads simples, StringBuffer n'est pas significativement 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 un benchmark, 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: 2
Constructeur: 7!

Ainsi, les constructeurs sont plus rapides que les tampons et beaucoup plus rapidement que la concaténation de chaînes. Utilisons maintenant un Executor 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, StringBuffers prend 157 ms pour 100 000 ajouts. Ce n'est pas le même test, mais comparé aux 37 ms précédents, vous pouvez sans risque supposer que les ajouts de StringBuffers sont plus lents avec l'utilisation de la lecture multiple. La raison en est que le JIT/hotspot/compiler/quelque chose fait des optimisations quand il détecte qu'il n'y a pas besoin de vérifier les verrous.

Mais avec StringBuilder, vous avez Java.lang.ArrayIndexOutOfBoundsException, car un thread concurrent tente d'ajouter quelque chose là où il ne devrait pas.

La conclusion est que vous ne devez pas chasser StringBuffers. Et là où vous avez des discussions, réfléchissez à ce qu’elles font, avant d’essayer de gagner quelques nanosecondes.

49
Nicolas Zozol

StringBuilder a été introduit dans Java 1.5. Il ne fonctionnera donc pas avec les machines virtuelles antérieures.

Depuis le Javadocs :

La classe StringBuilder fournit une API compatible avec StringBuffer, mais sans garantie de synchronisation. Cette classe est conçue pour être utilisée comme remplacement immédiat 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 plutôt que StringBuffer, car elle sera plus rapide dans la plupart des mises en œuvre.

41
Marc Novakowski

Très 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.

35
Sireesh Yarlagadda

StringBuilder n'est pas thread-safe. String Buffer est. Plus d'infos ici .

EDIT: En ce qui concerne les performances, après hotspot , StringBuilder est le gagnant. Cependant, pour de petites itérations, la différence de performances est négligeable.

22
Learning

StringBuffer

  • Synchronisé donc threadsafe
  • Fil sécuritaire 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 StringBuffer sans autre changement
21
JRomio

StringBuilder et StringBuffer sont presque identiques. La différence est que StringBuffer est synchronisé et que StringBuilder ne l’est pas. Bien que StringBuilder soit plus rapide que StringBuffer, la différence de performances est très faible. StringBuilder remplace Sun par StringBuffer. Cela é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 d'utiliser StringBuffer. Si votre texte va changer mais est utilisé par un seul fil, utilisez StringBuilder.

21
subodh ray

StringBuffer

StringBuffer est modifiable 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 a aussi des inconvénients car les performances du StringBuffer sont atteintes en raison de la propriété thread-safe. Ainsi, StringBuilder est plus rapide que StringBuffer lorsqu'il appelle les mêmes méthodes de chaque classe.

La valeur de StringBuffer peut être changée, cela signifie qu’elle peut être assignée à la nouvelle valeur. De nos jours, c’est la 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 dans le tas et qu'il peut également être modifié. La principale différence entre StringBuffer et StringBuilder est que StringBuilder n'est également pas thread-safe. StringBuilder est rapide car il n'est pas thread-safe.

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

enter image description here

Ressource: String Vs StringBuffer Vs StringBuilder

18
Virtual

String est un immuable.

StringBuffer est un mutable et synchronisé.

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

16
sudhakar

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 comme remplacement immédiat 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 plutôt que StringBuffer, car elle sera plus rapide dans la plupart des mises en œuvre.

11
skaffman

StringBuilder (introduit dans Java 5) est identique à StringBuffer, sauf que ses méthodes ne sont pas synchronisées. Cela signifie que ses performances sont meilleures que celles-ci, mais l’inconvénient est qu’il n’est pas thread-safe.

Lire tutoriel pour plus de détails.

10

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

    }
}
6
Kevin Lee

StringBuffer:

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

StringBuilder

  • Fil unique
  • Non synchronisé
  • Plus rapide que jamais String
4
Asif Mushtaq

Générateur de cordes:

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é du thread est nécessaire, la meilleure option est d'utiliser les objets StringBuffer.

4
Avinash

Mieux vaut utiliser StringBuilder car il n’est pas synchronisé et donc de meilleures performances. StringBuilder est un remplacement immédiat de l'ancien StringBuffer.

4
Niclas

StringBuffer est modifiable. Cela peut changer en termes de longueur et de contenu. StringBuffers sont thread-safe, ce qui signifie qu'ils disposent de méthodes synchronisées pour contrôler l'accès, de sorte qu'un seul thread puisse accéder au code synchronisé d'un objet StringBuffer à la fois. Ainsi, les objets StringBuffer peuvent généralement être utilisés en toute sécurité dans un environnement multi-thread 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, à la différence que son accès n'est pas synchronisé, de sorte qu'il n'est pas thread-safe. En l'absence de synchronisation, les performances de StringBuilder peuvent être meilleures que celles de StringBuffer. Ainsi, si vous travaillez dans un environnement à un seul thread, utiliser StringBuilder au lieu de StringBuffer peut entraîner une augmentation des performances. Ceci est également vrai pour d'autres situations telles qu'une variable locale StringBuilder (c'est-à-dire une variable dans une méthode) dans laquelle un seul thread accédera à un objet StringBuilder.

4
Android Genius

StringBuffer est synchronisé, mais StringBuilder ne l’est pas. En conséquence, StringBuilder est plus rapide que StringBuffer.

4
Ahmad adawi

Puisque StringBuffer est synchronisé, il nécessite un effort supplémentaire, donc basé sur les performances, il est un peu plus lent que StringBuilder.

3
Shuhail Kadavath

Il n'y a pas de différences fondamentales entre StringBuilder et StringBuffer, seules quelques différences existent entre eux. Dans StringBuffer, les méthodes sont synchronisées. Cela signifie qu’à la fois, un seul thread peut les exploiter. S'il y a plus d'un thread, le second devra attendre que le premier soit terminé et le troisième devra attendre que les premier et deuxième finissent, etc. Cela ralentit considérablement le processus et par conséquent, les performances dans le cas de StringBuffer sont faibles.

D'autre part, StringBuilder n'est pas synchronisé. Cela signifie qu’à la fois, plusieurs threads peuvent fonctionner simultanément sur le même objet StrinBuilder. Cela rend le processus très rapide et par conséquent, les performances de StringBuilder sont élevées.

3
Pratik Paul

StringBuffer est utilisé pour stocker des chaînes de caractères qui seront modifiées (les objets String ne peuvent pas être modifiés). Il se développe automatiquement selon les besoins. Classes connexes: String, CharSequence.

StringBuilder a été ajouté dans Java 5. Il est identique à tous égards à StringBuffer, à la différence qu'il n'est pas synchronisé, ce qui signifie que des problèmes peuvent survenir si plusieurs threads y accèdent en même temps. Pour les programmes à un seul thread, le cas le plus courant consiste à éviter très rapidement la synchronisation, ce qui rend le StringBuilder très légèrement plus rapide.

3
abhishek pathak

La principale différence est que StringBuffer est synchronisé mais StringBuilder ne l'est pas.Si vous devez utiliser plus d'un thread, StringBuffer est recommandé.Mais, selon la vitesse d'exécution StringBuilder est plus rapide que StringBuffer, car ce n'est pas synchronisé.

2
JDGuide

String est un objet immuable, ce qui signifie que la valeur ne peut pas être modifiée car StringBuffer est mutable.

StringBuffer est synchronisé, donc thread-safe, où StringBuilder ne l'est pas et ne convient que pour les instances à un seul thread.

2
Ketan Patel

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.

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

Puisque append est synchronized, StringBuffer a un surcoût de performance par rapport à StrinbBuilder dans un scénario multitâche. Tant que vous ne partagez pas le tampon entre plusieurs threads, utilisez StringBuilder, ce qui est rapide en raison de l'absence de synchronized dans les méthodes d'ajout.

2
Ravindra babu
  • StringBuffer est thread-safe, mais StringBuilder n'est pas thread-safe.
  • StringBuilder est plus rapide que StringBuffer.
  • StringBuffer est synchronisé alors que StringBuilder n'est pas synchronisé.
1
Praveen Kishor

Voici le résultat des tests de performance 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");

  }

Exécute-moi sur ideone

Résultat :

100 000 itérations pour l'ajout d'un seul texte

String - 37489 ms
String Buffer - 5 ms
String Builder - 4 ms

10000 itérations pour l'ajout d'un seul texte

String - 389 ms
String Buffer - 1 ms
String Builder - 1 ms
1
Ganesa Vijayakumar

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

0
G.Brown

Chaque méthode présente dans StringBuffer est synchronisée. Par conséquent, à la fois, un seul thread est autorisé à utiliser l'objet StringBuffer. Il augmente le temps d'attente d'un thread et crée des problèmes de performances pour résoudre ce problème. Sun People a introduit StringBuilder dans la version 1.5.

0
Srinivas