Quelle est la différence lors de la concaténation d’une chaîne en tant que variable avec un caractère ou une concaténation avec une autre chaîne?

Quand je vois quelque chose (pseudo 1-liner) comme ceci:

str1 + "a" + str2 

Est-ce bien pire (ou meilleur / égal) que le suivant (pseudo 1-liner)?

 str1 + 'a' + str2 

Mise à jour: meilleur exemple (par @QPaysTaxes) pour réduire la confusion concernant mon exemple original.

Ce que j’ai essayé: Différentes choses au cours des 10 dernières années de programmation Java, mais je n’ai jamais vraiment réussi à voir ce qu’il y avait sous le capot – par exemple, je suppose que le second est légèrement plus rapide / meilleur car il n’ya pas de Ssortingng-Object créé (s) pour la barre oblique et / ou le ramasse-miettes de Java doit en gérer moins. Une fois que j’ai préparé les certificates Java et que j’aurais peut-être été mieux argumenté à ce moment-là, il semble que même dans l’affaire quotidienne, la “théorie” sur Java doit également être mise à jour … meilleure explication que mon hypothèse selon laquelle indexOf('c') devrait être utilisé plutôt que indexOf("C") et je me demandais si indexOf("C") la même chose pour la concaténation de chaînes.

J’ai aussi googlé un peu mais comme mon titre l’indique peut-être, je ne suis pas assez bon pour décrire ce que je cherche sans exemple. Je suis désolé pour cela et la possibilité que ce handicap vient de produire un duplicata.

Ce que je vais essayer: D’après la réponse acceptée ici Concaténation de chaînes: opérateur concat () vs “+”, j’espère être en mesure de commencer à voir ce qui se cache sous le capot et de pouvoir un jour pouvoir discuter / répondre à de telles questions .

Sur la base de la réponse acceptée, j’espère pouvoir commencer à voir ce qui se cache sous le capot.

Regardons le bytecode généré lors de la concaténation d’une chaîne avec un caractère:

 Ssortingng str1 = "a" + "test"; Ssortingng str2 = 'a' + "test"; 

 0: ldc #2 // Ssortingng atest 2: astore_1 3: ldc #2 // Ssortingng atest 5: astore_2 

comme vous pouvez le constater, il n’y a pas de différence, le compilateur le convertira en même code binary.

Examinons maintenant le bytecode généré lors de la concaténation d’un caractère dans une variable Ssortingng.

 Ssortingng str1 = "a" + str3; //str3 is a Ssortingng Ssortingng str2 = 'a' + str3; 

  7: invokespecial #4 // Method java/lang/SsortingngBuilder."":()V 10: ldc #5 // Ssortingng a 12: invokevirtual #6 // Method java/lang/SsortingngBuilder.append:(Ljava/lang/Ssortingng;)Ljava/lang/SsortingngBuilder; 15: aload_1 16: invokevirtual #6 // Method java/lang/SsortingngBuilder.append:(Ljava/lang/Ssortingng;)Ljava/lang/SsortingngBuilder; 19: invokevirtual #7 // Method java/lang/SsortingngBuilder.toSsortingng:()Ljava/lang/Ssortingng; 22: astore_2 23: new #3 // class java/lang/SsortingngBuilder 26: dup 27: invokespecial #4 // Method java/lang/SsortingngBuilder."":()V 30: bipush 97 32: invokevirtual #8 // Method java/lang/SsortingngBuilder.append:(C)Ljava/lang/SsortingngBuilder; 35: aload_1 36: invokevirtual #6 // Method java/lang/SsortingngBuilder.append:(Ljava/lang/Ssortingng;)Ljava/lang/SsortingngBuilder; 39: invokevirtual #7 // Method java/lang/SsortingngBuilder.toSsortingng:()Ljava/lang/Ssortingng; 

Comme vous pouvez le constater, il y a une petite différence.

 10: ldc #5 // Ssortingng a 

ldc une constante #index depuis un pool constant (Ssortingng, int ou float) sur la stack.

Par conséquent, si vous concaténez directement avec une variable, concaténer un caractère génèrera moins de bytecode, c’est ce qu’il y a sous le capot .

Maintenant, pour le problème de performance, cela ne représentera aucune différence de performance significative car le compilateur JIT optimisera la plupart des objects temporaires, sauf indication contraire lors de l’exécution de votre programme pour désactiver le compilateur JIT à l’aide de -Djava.comstackr=NONE .

Je préfère utiliser "a" au lieu de 'a' pour m’assurer que le résultat est une Ssortingng .

Considère ceci:

 public static void main(Ssortingng... args) { Ssortingng s = "foo"; int i = 1; Object arg = s + '/' + i; log(arg); } private static void log(Object... args) { MessageFormat format = new MessageFormat("bar {0}"); Ssortingng message = format.format(args); System.out.println(message); // or write to a log or something } 

Supposons que vous décidiez de ne plus avoir besoin de s dans le message et changez la troisième ligne de la méthode main pour:

 Object arg = '/' + i; 

Ensuite, arg contiendra juste un nombre, car car char + int ne concatène pas, mais ajoute les valeurs.

Si vous construisez un nom de fichier, vous l’utiliserez par la suite. Dans la plupart des cas, cela implique un access à un support physique dont la magnitude est plus lente que tout ce que vous pouvez faire de mal en concaténant vos chaînes. Alors, faites ce qui est maintenable et ne vous souciez pas des performances dans ce cas particulier.

Lors de la création de noms de fichiers, mon conseil est d’utiliser la classe File ou Path que les séparateurs de chemin soient automatiquement corrects.

EDIT: Comme vous le soulignez dans votre commentaire, votre question concerne le cas général. Il suffit de regarder la source. SsortingngBuilder.append(Ssortingng) termine par System.arraycopy() dans Ssortingng.getChars() tandis que SsortingngBuilder.append(char) copie directement un seul caractère. Donc, en théorie, SsortingngBuilder.append(char) sera plus rapide.

Cependant, il vous faudra évaluer cela pour voir si cela fait une différence dans la pratique.

Je ne sais pas si l’une ou l’autre des options est meilleure en termes de performances, mais je peux penser à un autre problème à considérer, celui qui préférerait le premier extrait.

Le compilateur peut mieux vous protéger contre les fautes de frappe si vous ajoutez des primitives au lieu de la représentation sous forme de chaîne de ces primitives.

Considérer:

 Ssortingng plus10 = "plus" + 10; 

Si vous tapez par erreur

 Ssortingng plus10 = "plus" + 1O; 

Le compilateur vous donnera une erreur.

Si, en revanche, vous tapez

 Ssortingng plus10 = "plus" + "1O"; 

Le compilateur n’aura aucun problème avec cela.

Il en va de même pour les caractères ajoutés

 Ssortingng plus = "x" + '++' + "y"; 

ne comstackra pas

 Ssortingng plus = "x" + "++" + "y"; 

passera la compilation.

Bien sûr, il serait préférable d’utiliser des constantes et non des valeurs codées en dur (et d’append à un SsortingngBuilder au lieu d’utiliser une concaténation de Ssortingng ), mais même pour les constantes, je préférerais les types primitifs aux chaînes, car ils vous offrent un niveau de protection supplémentaire. contre les erreurs.

Regarder le code source aide souvent à comprendre ce qui se passe.

 Ssortingng s = s1 + s2 

Va exécuter:

 Ssortingng s = new SsortingngBuilder(s1).append(s2).toSsortingng(); 

Examinez maintenant le code source pour append (char) et append (ssortingng) de la classe SsortingngBuilder :

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/AbstractSsortingngBuilder.java#AbstractSsortingngBuilder.append%28char%28char%29

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/AbstractSsortingngBuilder.java#AbstractSsortingngBuilder.append%28java.lang.lang.Ssortingng%29

Vous verrez que append (ssortingng) effectue plus de vérifications pour voir si la chaîne est nulle ou vide. Cependant, vous ne remarquerez probablement aucune différence.

Il n’y a pas de différence significative dans la performance en réalité. En moyenne, la concaténation de chaînes prend le même temps.

Cependant, le compilateur Java interne remplace l’opérateur + avec SsortingngBuilder au moment de la compilation.

Ainsi, en utilisant l’opérateur + avec char, le compilateur le convertira en SsortingngBuilder interne et utilisera .append(char) . La même chose se produira avec une chaîne, avec une différence qu’elle utilisera .append(Ssortingng) .

Et comme je l’ai mentionné ci-dessus, il n’y a pas de différence en moyenne. Un simple test montrera que la différence de temps est proche de 0. Il s’agit donc vraiment d’une question de lisibilité. Et du sharepoint vue de la lisibilité, si vous concentrez des chaînes, il est préférable de conserver le même type et d’utiliser Ssortingng même pour des caractères uniques, plutôt que des caractères.

C’est ce qui se cache sous le capot: Ssortingng str = s1 + "/"; crée essentiellement 2 nouveaux objects Ssortingng distincts ( str et new Ssortingng("/")) .

Ce n’est pas un problème pour les petits logiciels, mais pensez-y en termes de mémoire si vous deviez créer 2 objects Ssortingng (gardez à l’esprit: les objects réservent une entrée dans la stack plus le contenu conservé dans le tas) pour n> 500 000 entrées dans la firebase database.

L’utilisation de guillemets simples, comme Ssortingng str = s1 + '/' , entraînera entièrement un autre processus. '/' représente la valeur de représentation numérique des caractères ASCii, quel que soit le caractère écrit entre les guillemets. Cette opération a une exécution constante ( O (1) ) (pensez à un access instantané à un tableau) et sera naturellement plus rapide que la création et la référence d’objects.

Comme de nombreuses personnes l’ont déjà suggéré, l’utilisation d’un object SsortingngBuilder pour la concaténation de chaînes est beaucoup plus facile en mémoire que la création de chaînes avec l’opérateur +.