web-dev-qa-db-fra.com

StringBuilder vs Concaténation de chaînes dans toString () dans Java

Étant donné les implémentations 2 toString() ci-dessous, laquelle est préférée:

public String toString(){
    return "{a:"+ a + ", b:" + b + ", c: " + c +"}";
}

ou

public String toString(){
    StringBuilder sb = new StringBuilder(100);
    return sb.append("{a:").append(a)
          .append(", b:").append(b)
          .append(", c:").append(c)
          .append("}")
          .toString();
}

?

Plus important encore, étant donné que nous n’avons que 3 propriétés, cela ne fera peut-être pas une différence, mais à quel moment changeriez-vous de + concat en StringBuilder?

868
non sequitor

La version 1 est préférable car elle est plus courte et le compilateur la transformera en version 2 - aucune différence de performance.

Plus important encore, étant donné que nous n’avons que 3 propriétés, cela ne fera peut-être pas une différence, mais à quel moment passez-vous de concat en constructeur?

Au moment où vous êtes en train de concaténer une boucle, c'est généralement lorsque le compilateur ne peut pas remplacer StringBuilder par lui-même.

911

La clé est de savoir si vous écrivez une seule concaténation au même endroit ou si vous l’accumulez avec le temps.

Pour l'exemple que vous avez donné, il est inutile d'utiliser explicitement StringBuilder. (Regardez le code compilé pour votre premier cas.)

Mais si vous construisez une chaîne, par exemple dans une boucle, utilisez StringBuilder.

Pour clarifier, en supposant que hugeArray contient des milliers de chaînes, codez comme ceci:

...
String result = "";
for (String s : hugeArray) {
    result = result + s;
}

est une perte de temps et de mémoire comparée à:

...
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {
    sb.append(s);
}
String result = sb.toString();
233
joel.neely

Je préfère:

String.format( "{a: %s, b: %s, c: %s}", a, b, c );

... parce que c'est court et lisible.

Je n'optais pas pour la vitesse, sauf si vous l'utilisiez dans une boucle avec un nombre de répétitions très élevé et ont mesuré la différence de performance.

Je conviens que si vous devez générer beaucoup de paramètres, ce formulaire peut être déroutant (comme le dit l’un des commentaires). Dans ce cas, je passerais à une forme plus lisible (peut-être en utilisant ToStringBuilder de Apache-commons - tiré de la réponse de matt b) et en ignorant à nouveau les performances.

71
tangens

Dans la plupart des cas, vous ne verrez pas de différence réelle entre les deux approches, mais il est facile de construire un scénario du pire cas comme celui-ci:

public class Main
{
    public static void main(String[] args)
    {
        long now = System.currentTimeMillis();
        slow();
        System.out.println("slow elapsed " + (System.currentTimeMillis() - now) + " ms");

        now = System.currentTimeMillis();
        fast();
        System.out.println("fast elapsed " + (System.currentTimeMillis() - now) + " ms");
    }

    private static void fast()
    {
        StringBuilder s = new StringBuilder();
        for(int i=0;i<100000;i++)
            s.append("*");      
    }

    private static void slow()
    {
        String s = "";
        for(int i=0;i<100000;i++)
            s+="*";
    }
}

La sortie est:

slow elapsed 11741 ms
fast elapsed 7 ms

Le problème est que + + ajouter à une chaîne reconstruit une nouvelle chaîne, de sorte qu'il en coûte quelque chose de linéaire pour la longueur de vos chaînes (somme des deux).

Donc - à votre question:

La deuxième approche serait plus rapide, mais moins lisible et plus difficile à maintenir. Comme je l'ai dit, dans votre cas particulier, vous ne verriez probablement pas la différence.

70
Omry Yadan

Je me suis également heurté à mon patron sur le fait d'utiliser append ou +. Comme ils utilisent Append (je n'arrive toujours pas à comprendre ce qu'ils disent chaque fois qu'un nouvel objet est créé). J'ai donc pensé à faire de la recherche et du développement. Bien que j'aime l'explication de Michael Borgwardt, je voulais simplement montrer une explication si quelqu'un aurait vraiment besoin de savoir à l'avenir.

/**
 *
 * @author Perilbrain
 */
public class Appc {
    public Appc() {
        String x = "no name";
        x += "I have Added a name" + "We May need few more names" + Appc.this;
        x.concat(x);
        // x+=x.toString(); --It creates new StringBuilder object before concatenation so avoid if possible
        //System.out.println(x);
    }

    public void Sb() {
        StringBuilder sbb = new StringBuilder("no name");
        sbb.append("I have Added a name");
        sbb.append("We May need few more names");
        sbb.append(Appc.this);
        sbb.append(sbb.toString());
        // System.out.println(sbb.toString());
    }
}

et le démontage de la classe ci-dessus sort comme

 .method public <init>()V //public Appc()
  .limit stack 2
  .limit locals 2
met001_begin:                                  ; DATA XREF: met001_slot000i
  .line 12
    aload_0 ; met001_slot000
    invokespecial Java/lang/Object.<init>()V
  .line 13
    ldc "no name"
    astore_1 ; met001_slot001
  .line 14

met001_7:                                      ; DATA XREF: met001_slot001i
    new Java/lang/StringBuilder //1st object of SB
    dup
    invokespecial Java/lang/StringBuilder.<init>()V
    aload_1 ; met001_slot001
    invokevirtual Java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    ldc "I have Added a nameWe May need few more names"
    invokevirtual Java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    aload_0 ; met001_slot000
    invokevirtual Java/lang/StringBuilder.append(Ljava/lang/Object;)Ljava/lan\
g/StringBuilder;
    invokevirtual Java/lang/StringBuilder.toString()Ljava/lang/String;
    astore_1 ; met001_slot001
  .line 15
    aload_1 ; met001_slot001
    aload_1 ; met001_slot001
    invokevirtual Java/lang/String.concat(Ljava/lang/String;)Ljava/lang/Strin\
g;
    pop
  .line 18
    return //no more SB created
met001_end:                                    ; DATA XREF: met001_slot000i ...

; ===========================================================================

;met001_slot000                                ; DATA XREF: <init>r ...
    .var 0 is this LAppc; from met001_begin to met001_end
;met001_slot001                                ; DATA XREF: <init>+6w ...
    .var 1 is x Ljava/lang/String; from met001_7 to met001_end
  .end method
;44-1=44
; ---------------------------------------------------------------------------


; Segment type: Pure code
  .method public Sb()V //public void Sb
  .limit stack 3
  .limit locals 2
met002_begin:                                  ; DATA XREF: met002_slot000i
  .line 21
    new Java/lang/StringBuilder
    dup
    ldc "no name"
    invokespecial Java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    astore_1 ; met002_slot001
  .line 22

met002_10:                                     ; DATA XREF: met002_slot001i
    aload_1 ; met002_slot001
    ldc "I have Added a name"
    invokevirtual Java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 23
    aload_1 ; met002_slot001
    ldc "We May need few more names"
    invokevirtual Java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 24
    aload_1 ; met002_slot001
    aload_0 ; met002_slot000
    invokevirtual Java/lang/StringBuilder.append(Ljava/lang/Object;)Ljava/lan\
g/StringBuilder;
    pop
  .line 25
    aload_1 ; met002_slot001
    aload_1 ; met002_slot001
    invokevirtual Java/lang/StringBuilder.toString()Ljava/lang/String;
    invokevirtual Java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 28
    return
met002_end:                                    ; DATA XREF: met002_slot000i ...


;met002_slot000                                ; DATA XREF: Sb+25r
    .var 0 is this LAppc; from met002_begin to met002_end
;met002_slot001                                ; DATA XREF: Sb+9w ...
    .var 1 is sbb Ljava/lang/StringBuilder; from met002_10 to met002_end
  .end method
;96-49=48
; ---------------------------------------------------------------------------

Parmi les deux codes ci-dessus, vous pouvez constater que Michael a raison. Dans chaque cas, un seul objet SB est créé.

27
perilbrain

Depuis Java 1.5, une concaténation simple en une ligne avec "+" et StringBuilder.append () génèrent exactement le même bytecode.

Donc, dans un souci de lisibilité du code, utilisez "+".

2 exceptions:

  • environnement multithread: StringBuffer
  • concaténation en boucles: StringBuilder/StringBuffer
24
Zofren

En utilisant la dernière version de Java (1.8), le désassemblage (javap -c) montre l'optimisation introduite par le compilateur. + ainsi que sb.append() générera un code très similaire. Cependant, il sera utile de vérifier le comportement si nous utilisons + dans une boucle for.

Ajout de chaînes en utilisant + dans une boucle for

Java:

public String myCatPlus(String[] vals) {
    String result = "";
    for (String val : vals) {
        result = result + val;
    }
    return result;
}

ByteCode: (for extrait de la boucle)

12: iload         5
14: iload         4
16: if_icmpge     51
19: aload_3
20: iload         5
22: aaload
23: astore        6
25: new           #3                  // class Java/lang/StringBuilder
28: dup
29: invokespecial #4                  // Method Java/lang/StringBuilder."<init>":()V
32: aload_2
33: invokevirtual #5                  // Method Java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
36: aload         6
38: invokevirtual #5                  // Method Java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
41: invokevirtual #6                  // Method Java/lang/StringBuilder.toString:()Ljava/lang/String;
44: astore_2
45: iinc          5, 1
48: goto          12

Ajout de chaînes en utilisant stringbuilder.append

Java:

public String myCatSb(String[] vals) {
    StringBuilder sb = new StringBuilder();
    for(String val : vals) {
        sb.append(val);
    }
    return sb.toString();
}

ByteCdoe: (for extrait de la boucle)

17: iload         5
19: iload         4
21: if_icmpge     43
24: aload_3
25: iload         5
27: aaload
28: astore        6
30: aload_2
31: aload         6
33: invokevirtual #5                  // Method Java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
36: pop
37: iinc          5, 1
40: goto          17
43: aload_2

Il y a un peu de différence flagrante si. Dans le premier cas, où + a été utilisé, un nouveau StringBuilder est créé pour chaque itération de boucle for et le résultat généré est enregistré en effectuant un appel toString() (29 à 41). Vous générez donc des chaînes intermédiaires dont vous n’avez vraiment pas besoin lorsque vous utilisez l’opérateur + dans la boucle for.

22
ring bearer

Dans Java 9, la version 1 devrait être plus rapide car elle est convertie en appel invokedynamic. Plus de détails peuvent être trouvés dans JEP-28 :

L'idée est de remplacer la danse entière de StringBuilder par un simple appel invoqué dynamique à Java.lang.invoke.StringConcatFactory, qui acceptera les valeurs nécessitant une concaténation.

10
ZhekaKozlov

Pour des raisons de performances, l'utilisation de la concaténation += (String) est déconseillée. La raison en est: Java String est immuable, chaque fois qu'une nouvelle concaténation est effectuée, une nouvelle String est créée (la nouvelle empreinte digitale est déjà différente de celle de l'ancienne). dans le pool String ). La création de nouvelles chaînes met la pression sur le CPG et ralentit le programme: la création d'objets coûte cher.

Le code ci-dessous devrait le rendre plus pratique et plus clair en même temps.

public static void main(String[] args) 
{
    // warming up
    for(int i = 0; i < 100; i++)
        RandomStringUtils.randomAlphanumeric(1024);
    final StringBuilder appender = new StringBuilder();
    for(int i = 0; i < 100; i++)
        appender.append(RandomStringUtils.randomAlphanumeric(i));

    // testing
    for(int i = 1; i <= 10000; i*=10)
        test(i);
}

public static void test(final int howMany) 
{
    List<String> samples = new ArrayList<>(howMany);
    for(int i = 0; i < howMany; i++)
        samples.add(RandomStringUtils.randomAlphabetic(128));

    final StringBuilder builder = new StringBuilder();
    long start = System.nanoTime();
    for(String sample: samples)
        builder.append(sample);
    builder.toString();
    long elapsed = System.nanoTime() - start;
    System.out.printf("builder - %d - elapsed: %dus\n", howMany, elapsed / 1000);

    String accumulator = "";
    start = System.nanoTime();
    for(String sample: samples)
        accumulator += sample;
    elapsed = System.nanoTime() - start;
    System.out.printf("concatenation - %d - elapsed: %dus\n", howMany, elapsed / (int) 1e3);

    start = System.nanoTime();
    String newOne = null;
    for(String sample: samples)
        newOne = new String(sample);
    elapsed = System.nanoTime() - start;
    System.out.printf("creation - %d - elapsed: %dus\n\n", howMany, elapsed / 1000);
}

Les résultats d'une analyse sont indiqués ci-dessous.

builder - 1 - elapsed: 132us
concatenation - 1 - elapsed: 4us
creation - 1 - elapsed: 5us

builder - 10 - elapsed: 9us
concatenation - 10 - elapsed: 26us
creation - 10 - elapsed: 5us

builder - 100 - elapsed: 77us
concatenation - 100 - elapsed: 1669us
creation - 100 - elapsed: 43us

builder - 1000 - elapsed: 511us
concatenation - 1000 - elapsed: 111504us
creation - 1000 - elapsed: 282us

builder - 10000 - elapsed: 3364us 
concatenation - 10000 - elapsed: 5709793us
creation - 10000 - elapsed: 972us

Sans tenir compte des résultats pour 1 concaténation (JIT ne faisait pas encore son travail), même pour 10 concaténations, la pénalité de performance est pertinente; pour des milliers de concaténations, la différence est énorme.

Leçons tirées de cette expérience très rapide (facilement reproductible avec le code ci-dessus): n'utilisez jamais le += pour concaténer des chaînes, même dans les cas très élémentaires où quelques concaténations sont nécessaires (comme dit, créer de nouvelles chaînes coûte quand même cher et met la pression sur le GC).

7
Paolo Maresca

Apache Commons-Lang a une classe ToStringBuilder qui est super facile à utiliser. Il fait un bon travail en gérant à la fois la logique d’ajout et la mise en forme de ce que vous souhaitez pour votre toString.

public void toString() {
     ToStringBuilder tsb =  new ToStringBuilder(this);
     tsb.append("a", a);
     tsb.append("b", b)
     return tsb.toString();
}

Renverra une sortie qui ressemble à com.blah.YourClass@abc1321f[a=whatever, b=foo].

Ou sous une forme plus condensée utilisant le chaînage:

public void toString() {
     return new ToStringBuilder(this).append("a", a).append("b", b").toString();
}

Ou si vous souhaitez utiliser la réflexion pour inclure tous les champs de la classe:

public String toString() {
    return ToStringBuilder.reflectionToString(this);
}

Vous pouvez également personnaliser le style de ToString si vous le souhaitez.

7
matt b

Rendez la méthode toString aussi lisible que possible!

La seule exception à cette règle dans mon livre est si vous pouvez me prouver qu'il consomme des ressources importantes :) (Oui, cela signifie le profilage)

Notez également que le compilateur Java 5 génère un code plus rapide que l'approche manuscrite "StringBuffer" utilisée dans les versions antérieures de Java. Si vous utilisez "+" ceci et les améliorations futures sont gratuits.

Il semble y avoir un débat quant à savoir si l'utilisation de StringBuilder est toujours nécessaire avec les compilateurs actuels. Alors j'ai pensé donner mon 2 centimes d'expérience.

J'ai _ un ensemble de résultats JDBC de 10 000 enregistrements (oui, il me faut tous les éléments d'un lot.) L'utilisation de l'opérateur + prend environ 5 minutes sur ma machine avec Java 1.8. L'utilisation de stringBuilder.append("") prend moins d'une seconde pour la même requête.

Donc la différence est énorme. À l'intérieur d'une boucle, StringBuilder est beaucoup plus rapide.

3
Eddy

En termes de performances, la concaténation de chaînes utilisant '+' est plus coûteuse, car elle doit créer une nouvelle copie de String car les chaînes sont immuables en Java. Cela joue un rôle particulier si la concaténation est très fréquente, par exemple: dans une boucle. Voici ce que mon IDEA suggère lorsque je tente de faire une chose pareille:

enter image description here

Règles générales:

  • Dans une seule affectation de chaîne, l’utilisation de la concaténation de chaînes convient parfaitement.
  • Si vous souhaitez créer un grand bloc de données de caractères, optez pour StringBuffer.
  • Utiliser + = sur une chaîne sera toujours moins efficace que d'utiliser un StringBuffer, cela devrait donc faire sonner les cloches d'avertissement - mais dans certains cas, l'optimisation obtenue sera négligeable par rapport aux problèmes de lisibilité, utilisez donc votre bon sens.

Voici un blog de Nice Jon Skeet autour de ce sujet.

2
Sudip Bhandari

Voir l'exemple ci-dessous:

//Java8
static void main(String[] args) {
    case1();//str.concat
    case2();//+=
    case3();//StringBuilder
}

static void case1() {
    List<Long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    String str = "";
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str = str.concat(UUID.randomUUID()+"---");
        saveTime(savedTimes, startTime);
    }
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");
}

static void case2() {
    List<Long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    String str = "";
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str+=UUID.randomUUID()+"---";
        saveTime(savedTimes, startTime);
    }        
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");
}

static void case3() {
    List<Long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    StringBuilder str = new StringBuilder("");
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str.append(UUID.randomUUID()+"---");
        saveTime(savedTimes, startTime);
    }        
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");

}

static void saveTime(List<Long> executionTimes, long startTime) {
        executionTimes.add(System.currentTimeMillis()-startTime);
        if(executionTimes.size()%CALC_AVG_EVERY == 0) {
            out.println("average time for "+executionTimes.size()+" concatenations: "+
                    NumberFormat.getInstance().format(executionTimes.stream().mapToLong(Long::longValue).average().orElseGet(()->0))+
                    " ms avg");
            executionTimes.clear();
        }
}

Sortie:

temps moyen pour 10 000 concaténations: 0,096 ms en moyenne
temps moyen pour 10 000 concaténations: 0,185 ms en moyenne
temps moyen pour 10 000 concaténations: 0,327 ms en moyenne
temps moyen pour 10 000 concaténations: 0,501 ms en moyenne
temps moyen pour 10 000 concaténations: 0,656 ms en moyenne
Chaîne créée de longueur: 1950000 en 17745 ms
temps moyen pour 10 000 concaténations: 0,21 ms en moyenne
temps moyen pour 10 000 concaténations: 0,652 ms
temps moyen pour 10 000 concaténations: 1,129 ms
temps moyen pour 10 000 concaténations: 1,727 ms moyenne
temps moyen pour 10 000 concaténations: 2,302 ms
Chaîne de longueur créée: 1950000 en 60279 ms
temps moyen pour 10 000 concaténations: 0,002 ms
temps moyen pour 10 000 concaténations: 0,002 ms
temps moyen pour 10 000 concaténations: 0,002 ms
temps moyen pour 10 000 concaténations: 0,002 ms
temps moyen pour 10 000 concaténations: 0,002 ms
Chaîne créée de longueur: 1950000 en 100 ms

Lorsque la longueur de la chaîne augmente, le temps de la concaténation augmente également.
C’est là que la StringBuilder est absolument nécessaire.
Comme vous le voyez, la concaténation: UUID.randomUUID()+"---" n’affecte pas vraiment le temps.

P.S.: Je ne pense pas que quand utiliser StringBuilder en Java est vraiment une copie de ceci.
Cette question parle de toString() dont la plupart du temps n’effectue pas de concaténation d’énormes chaînes.

2
Marinos An

Puis-je préciser que si vous allez parcourir une collection et utiliser StringBuilder, vous pouvez vouloir vérifier Apache Commons Lang et StringUtils.join () (in différentes saveurs)?

Quelles que soient les performances, cela vous évitera de créer StringBuilders et des boucles for pour ce qui semble être le millionième temps.

1
Brian Agnew

J'ai comparé quatre approches différentes pour comparer les performances. Je ne sais pas exactement ce qui arrive à gc, mais l’important pour moi est le temps. Le compilateur est un facteur important ici. J'ai utilisé jdk1.8.0_45 sous la plate-forme window8.1.

concatWithPlusOperator = 8
concatWithBuilder = 130
concatWithConcat = 127
concatStringFormat = 3737
concatWithBuilder2 = 46


public class StringConcatenationBenchmark {

private static final int MAX_LOOP_COUNT = 1000000;

public static void main(String[] args) {

    int loopCount = 0;
    long t1 = System.currentTimeMillis();
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithPlusOperator();
        loopCount++;
    }
    long t2 = System.currentTimeMillis();
    System.out.println("concatWithPlusOperator = " + (t2 - t1));

    long t3 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithBuilder();
        loopCount++;
    }
    long t4 = System.currentTimeMillis();
    System.out.println("concatWithBuilder = " + (t4 - t3));

    long t5 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithConcat();
        loopCount++;
    }
    long t6 = System.currentTimeMillis();
    System.out.println("concatWithConcat = " + (t6 - t5));

    long t7 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatStringFormat();
        loopCount++;
    }
    long t8 = System.currentTimeMillis();
    System.out.println("concatStringFormat = " + (t8 - t7));

    long t9 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithBuilder2();
        loopCount++;
    }
    long t10 = System.currentTimeMillis();
    System.out.println("concatWithBuilder2 = " + (t10 - t9));
}

private static void concatStringFormat() {
    String s = String.format("%s %s %s %s ", "String", "String", "String", "String");
}

private static void concatWithConcat() {
    String s = "String".concat("String").concat("String").concat("String");
}

private static void concatWithBuilder() {
    StringBuilder builder=new StringBuilder("String");
    builder.append("String").append("String").append("String");
    String s = builder.toString();
}

private static void concatWithBuilder2() {
    String s = new StringBuilder("String").append("String").append("String").append("String").toString();
}

private static void concatWithPlusOperator() {
    String s = "String" + "String" + "String" + "String";
}
}
1
Hamedz

Voici ce que j'ai vérifié en Java8

  • Utilisation de la concaténation de chaînes
  • Utilisation de StringBuilder

    long time1 = System.currentTimeMillis();
    usingStringConcatenation(100000);
    System.out.println("usingStringConcatenation " + (System.currentTimeMillis() - time1) + " ms");
    
    time1 = System.currentTimeMillis();
    usingStringBuilder(100000);
    System.out.println("usingStringBuilder " + (System.currentTimeMillis() - time1) + " ms");
    
    
    private static void usingStringBuilder(int n)
    {
        StringBuilder str = new StringBuilder();
        for(int i=0;i<n;i++)
            str.append("myBigString");    
    }
    
    private static void usingStringConcatenation(int n)
    {
        String str = "";
        for(int i=0;i<n;i++)
            str+="myBigString";
    }
    

C'est vraiment un cauchemar si vous utilisez la concaténation de chaînes pour un grand nombre de chaînes.

usingStringConcatenation 29321 ms
usingStringBuilder 2 ms
0
nagendra547