1124 votes

StringBuilder vs concaténation de Chaîne dans toString() en Java

Compte tenu de la 2 toString() des implémentations ci-dessous, qui est privilégié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 biens qu'il ne peut pas faire une différence, mais à quel point souhaitez-vous basculer d' + concat à StringBuilder?

1136voto

Michael Borgwardt Points 181658

La Version 1 est préférable car il est plus court et le compilateur s'en fait le transformer en version 2 - pas de différence de performances que ce soit.

Plus important encore, étant donné que nous n'avons que 3 les propriétés qu'elle ne pourrait pas faire un différence, mais à quel point pensez-vous commutateur de concat pour builder?

Au point où vous êtes la concaténation dans une boucle - c'est généralement lorsque le compilateur ne peut pas se substituer StringBuilder par lui-même.

307voto

joel.neely Points 17059

La clé est de savoir si vous êtes l'écriture d'une simple concaténation de tous dans un endroit, ou accumuler au fil du temps.

Pour l'exemple que vous avez donné, il n'y a aucun point en utilisant explicitement StringBuilder. (Regardez le code compilé pour votre premier cas.)

Mais si vous êtes la construction d'une chaîne de caractères par exemple à l'intérieur d'une boucle, utiliser StringBuilder.

Pour clarifier, en supposant que hugeArray contient des milliers de chaînes de caractères, le code comme ceci:

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

beaucoup de temps et de mémoire de gaspillage par rapport à:

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

92voto

Omry Yadan Points 7523

Dans la plupart des cas, vous ne pourrez pas voir une réelle différence entre les deux approches, mais il est facile de construire un scénario du pire des 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, c'est que pour += ajouter à une chaîne reconstruit une nouvelle chaîne, si il en coûte quelque chose de linéaire de la longueur de vos chaînes (somme des deux).

Donc à votre question:

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

76voto

tangens Points 17733

Je préfère:

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

...parce que c'est court et facile à lire.

Je voudrais pas optimiser ce pour la vitesse, sauf si vous l'utilisez à l'intérieur d'une boucle avec un très grand nombre de répétitions et ont mesuré la différence de performances.

Je suis d'accord, que si vous avez à la sortie de beaucoup de paramètres, ce formulaire peut prêter à confusion (comme l'un des commentaires dire). Dans ce cas, j'aimerais passer à une forme plus lisible (peut-être en utilisant ToStringBuilder de apache commons - extrait de la réponse de matt b) et d'ignorer les performances de nouveau.

30voto

perilbrain Points 4400

J'ai également eu un clash avec mon patron sur le fait de savoir si l'utilisation d'ajout ou +.Comme ils sont en utilisant Append(je ne peux pas comprendre comme ils le disent à chaque fois qu'un nouvel objet est créé). J'ai donc pensé à faire quelques R&D. Bien que j'aime Michael Borgwardt explication mais je voulais juste montrer une explication si quelqu'un en aura 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 en tant que

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

À partir de ces deux codes, vous pouvez voir Michael est à droite.Dans chaque cas, une seule SB objet est créé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X