Meilleures pratiques / performances: mélanger StringBuilder.append avec String.concat

86

J'essaie de comprendre quelle est la meilleure pratique et pourquoi pour concaténer des littéraux de chaîne et des variables pour différents cas. Par exemple, si j'ai un code comme celui-ci

StringBuilder sb = new StringBuilder("AAAAAAAAAAAAA")
    .append(B_String).append("CCCCCCCCCCC").append(D_String)
    .append("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
    .append("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");

Est-ce la manière de procéder? À partir de cet article , j'ai remarqué que l' +opérateur sur Strings crée une nouvelle instance de StringBuilder, concatène les opérandes et renvoie une conversion de chaîne, ce qui semble beaucoup plus de travail que d'appeler .append(); donc si c'est vrai, alors c'est hors de question. Mais qu'en est-il String.concat()? Est-il approprié d'utiliser .append()pour chaque concaténation? Ou juste pour les variables, et les littéraux peuvent être ajoutés .concat()?

StringBuilder sb = new StringBuilder("AAAAAAAAAAAAA")
    .append(B_String.concat("CCCCCCCCCCC")).append(D_String
    .concat("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
    .concat("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));

Quelles sont les règles générales de bonnes pratiques et de performances pour faire face à ces situations? Mon hypothèse est-elle correcte +et ne devrait-elle tout simplement pas être utilisée?

Nick Rolando
la source
Je pense que vous l'avez. Les opinions diffèrent quant à savoir si String + "ne devrait vraiment pas être utilisé". Le fait est que vous comprenez les conséquences
ControlAltDel

Réponses:

184

+ opérateur

String s = s1 + s2

Dans les coulisses, cela se traduit par:

String s = new StringBuilder(s1).append(s2).toString();

Imaginez combien de travail supplémentaire cela ajoute si vous avez s1 + s2ici:

stringBuilder.append(s1 + s2)

au lieu de:

stringBuilder.append(s1).append(s2)

Plusieurs chaînes avec +

Il convient de noter que:

String s = s1 + s2 + s3 + ... +sN

se traduit par:

String s = new StringBuilder(s1).append(s2).append(s3)...apend(sN).toString();

concat()

String s = s1.concat(s2);

Stringcrée un char[]tableau qui peut s'adapter à la fois s1et s2. Copie s1et s2contenu dans ce nouveau tableau. Nécessite en fait moins de travail que l' +opérateur.

StringBuilder.append()

Maintient une char[]matrice interne qui se développe en cas de besoin. Aucun supplément char[]n'est créé si l'intérieur est suffisamment grand.

stringBuilder.append(s1.concat(s2))

fonctionne également mal car s1.concat(s2)crée un char[]tableau supplémentaire et des copies s1et s2vers celui-ci simplement pour copier ce nouveau contenu de tableau en interne StringBuilder char[].

Cela étant dit, vous devez utiliser append()tout le temps et ajouter des chaînes brutes (votre premier extrait de code est correct).

Tomasz Nurkiewicz
la source
Merci pour votre aide et l'explication approfondie; c'est ce dont j'avais vraiment besoin.
Nick Rolando
12
Bien que les versions plus récentes du compilateur optimisent automatiquement l'opérateur + vers un générateur de chaînes, ce n'est pas nécessairement une bonne chose de supposer que ce sera le cas, contrairement aux anciennes versions. Il y a un sujet très important qui est ignoré dans toute cette discussion qui est en fait l'un des principaux objectifs de StringBuilder qui est le pool de chaînes. L'utilisation d'un générateur de chaîne conserve tout sous forme de char [] et ne crée pas de chaîne intermédiaire comme le faisait l'opérateur + avant les optimisations du compilateur (utilisé pour faire un concat). L'utilisation de concat crée un objet String intermédiaire qui est mis en cache mais non utilisé.
LINEMAN78
Donc, si je fais une concaténation de déclaration unique (pas de déclarations multiples dans une méthode) sur plusieurs chaînes différentes. Ce serait correct de l'utiliser +sur les objets String au lieu de créer une StringBuilderconcaténation pour cette seule fois, car cela fera fondamentalement la même chose?
Nick Rolando
1
Et si je veux concaténer uniquement un caractère, est-il préférable d'utiliser .append ('\ n') au lieu de .append ("\ n")? Comme un caractère est un type primitif, et une chaîne est un objet?
vrwim
3
Efficacité de Java 2-ème édition : l' utilisation répétée de l'opérateur de concaténation de chaînes pour concaténer n chaînes nécessite un temps quadratique en n. Alors, est-ce toujours d'actualité?
gkiko
16

Le compilier optimise la concaténation +.

Donc

int a = 1;
String s = "Hello " + a;

se transforme en

new StringBuilder().append("Hello ").append(1).toString();

Il existe un excellent sujet ici expliquant pourquoi vous devriez utiliser l'opérateur +.

Andy Turner
la source
3
Le compilateur l'optimiserait en fait String s = "Hello World";puisque vous utilisez des littéraux.
ColinD le
@ColinD: +1. Je viens de modifier mon extrait.
3

L'optimisation est effectuée automatiquement par le compilateur.

Le compilateur Java2 convertira automatiquement les éléments suivants:

String s = s1 + s2; 

à

String s = (new StringBuffer()).append(s1).append(s2).toString();

Tiré directement du site Web Java Best Practices on Oracles.

Audacieux comme l'Amour
la source
2

Vous devriez toujours utiliser append.

concatcréer une nouvelle chaîne donc c'est assez comme +je pense.

Si vous concatou utilisez +avec 2 final String, la JVM peut effectuer une optimisation, c'est donc la même chose que d'ajouter dans ce cas.

alain.janinm
la source
1

Si vous concattez exactement deux chaînes, utilisez String.concat (crée une nouvelle chaîne en créant un nouveau tableau de caractères qui correspond aux deux chaînes et y copie les tableaux de caractères des deux chaînes).

Si vous concattez plusieurs chaînes (plus de deux) sur une seule ligne, utilisez + ou StringBuilder.append, cela n'a pas d'importance, car le compilateur convertit + en StringBuilder.append. C'est bon pour plusieurs chaînes car il maintient un tableau de caractères qui se développe selon les besoins.

Si vous concattez plusieurs chaînes sur plusieurs lignes, créez un StringBuilder et utilisez la méthode append. À la fin, lorsque vous avez terminé d'ajouter des chaînes au StringBuilder, utilisez la méthode .toString () pour en créer une chaîne. Pour la concatation sur plusieurs lignes, c'est plus rapide que la deuxième méthode, car la deuxième méthode créerait un nouveau StringBuilder sur chaque ligne, ajouterait les chaînes, puis reconstituerait String, tandis que la troisième méthode n'utilise qu'un seul StringBuilder pour l'ensemble.

Dakkaron
la source
0

Utiliser l' +opérateur est la meilleure pratique, il est également simple et lisible.

Le langage Java fournit un support spécial pour l'opérateur de concaténation de chaînes (+) et pour la conversion d'autres objets en chaînes. La concaténation de chaînes est implémentée via la classe StringBuilder (ou StringBuffer) et sa méthode append.

Document officiel: https://docs.oracle.com/javase/8/docs/api/java/lang/String.html

Do Nhu Vy
la source
0

au niveau du code d'octet, il n'y a pas de différence et nous n'y compromettons pas l'efficacité. En cas d'exécution au niveau du code d'octet, il doit passer par la méthode de surcharge d'opérateur non en ligne pour + en appelant append. puis au niveau du langage assembleur (Java est écrit en C et C produit des assemblys similaires à l'assembly, il y aura un appel de registre supplémentaire pour stocker + appel de méthode dans la pile et il y aura un push supplémentaire. (en réalité, le compilateur croisé pourrait optimiser + opérateur appel, dans ce cas, cela ne fait aucune différence avec efficacité.)

C'est une bonne pratique d'avoir un moyen d'augmenter la lisibilité. :)

Shevon Silva
la source
0

Personnellement, je préfère le formateur de chaînes d'Strings.format() une ligne simple et facile à lire .

String b = "B value";
String d = "D value";
String fullString = String.format("A %s C %s E F", b, d);
// Output: A B value C D value E F
T04435
la source
0

Toutes les réponses sont assez bonnes et explicatives. Mais j'ai senti que l'exploration d'autres techniques de concaténation de chaînes aiderait également - Guava Joiner, Streams, String.format, etc.

Pour des détails complets sur les performances de chaque technique de concaténation, java-string-concatenation-which-way-is-best .

En bref, les performances de concaténation varient sans. de chaînes à concaténer. Par exemple - pour concaténer 1 à 10 chaînes, ces techniques fonctionnent le mieux - StringBuilder, StringBuffer et Plus Operator. Et pour concaténer des centaines de chaînes - Guava Joiner, la bibliothèque stringsUtils d'Apache fonctionne également très bien.

Veuillez parcourir le blog ci-dessus. Cela explique vraiment très bien l'efficacité des performances.

Merci.

codeurAJ
la source