En supposant que la chaîne a et b:
a += b
a = a.concat(b)
Sous le capot, sont-ce la même chose?
Voici concat décompilé comme référence. J'aimerais pouvoir décompiler le+
opérateur pour voir ce que cela fait.
public String concat(String s) {
int i = s.length();
if (i == 0) {
return this;
}
else {
char ac[] = new char[count + i];
getChars(0, count, ac, 0);
s.getChars(0, i, ac, count);
return new String(0, count + i, ac);
}
}
java
string
concatenation
shsteimer
la source
la source
+
on puisse décompiler.StringBuffer
ouStringBuilder
- (thread dangereux donc plus rapide, à la placeRéponses:
Non, pas tout à fait.
Premièrement, il y a une légère différence de sémantique. Si
a
estnull
,a.concat(b)
lance alors unNullPointerException
maisa+=b
traitera la valeur d'origine dea
comme si elle l'étaitnull
. De plus, laconcat()
méthode accepte uniquement lesString
valeurs tandis que l'+
opérateur convertit silencieusement l'argument en chaîne (en utilisant latoString()
méthode pour les objets). Alors leconcat()
méthode est donc plus stricte dans ce qu'elle accepte.Pour regarder sous le capot, écrivez un cours simple avec
a += b;
Désassemblez maintenant avec
javap -c
(inclus dans le Sun JDK). Vous devriez voir une liste comprenant:Donc,
a += b
est l'équivalent deLa
concat
méthode devrait être plus rapide. Cependant, avec plus de chaînes, laStringBuilder
méthode gagne, au moins en termes de performances.Le code source de
String
etStringBuilder
(et sa classe de base package-private) est disponible dans src.zip du Sun JDK. Vous pouvez voir que vous créez un tableau de caractères (redimensionnant si nécessaire), puis le jetez lorsque vous créez la finaleString
. Dans la pratique, l'allocation de mémoire est étonnamment rapide.Mise à jour: Comme le note Pawel Adamski, les performances ont changé dans le HotSpot plus récent.
javac
produit toujours exactement le même code, mais le compilateur de bytecode triche. Les tests simples échouent complètement car le corps entier du code est jeté. La sommeSystem.identityHashCode
(nonString.hashCode
) montre que leStringBuffer
code a un léger avantage. Sous réserve de modifications lors de la publication de la prochaine mise à jour ou si vous utilisez une autre machine virtuelle Java. De @lukaseder , une liste des éléments intrinsèques de la JVM HotSpot .la source
javap -c
d'une classe compilée qui l'utilise. (Oh, comme dans la réponse. Il suffit d'interpréter le démontage du bytecode, ce qui ne devrait pas être si difficile.)StringBuilder
même lorsqu'il joint deux chaînes? S'ilString
inclut des méthodes statiques pour concaténer jusqu'à quatre chaînes, ou toutes les chaînes dans unString[]
, le code peut ajouter jusqu'à quatre chaînes avec deux allocations d'objet (le résultatString
et son supportchar[]
, ni une redondante), ni un nombre quelconque de chaînes avec trois allocations ( leString[]
résultatString
et le supportchar[]
, seul le premier étant redondant). En l'état, utiliser au mieux laStringBuilder
volonté , nécessitent quatre allocations, et il faudra copier tous les caractères deux fois.Niyaz est correct, mais il convient également de noter que l'opérateur spécial + peut être converti en quelque chose de plus efficace par le compilateur Java. Java a une classe StringBuilder qui représente une chaîne mutable non thread-safe. Lors de l'exécution d'un tas de concaténations de chaînes, le compilateur Java convertit silencieusement
dans
ce qui pour les grandes cordes est nettement plus efficace. Pour autant que je sache, cela ne se produit pas lorsque vous utilisez la méthode concat.
Cependant, la méthode concat est plus efficace lors de la concaténation d'une chaîne vide sur une chaîne existante. Dans ce cas, la JVM n'a pas besoin de créer un nouvel objet String et peut simplement retourner celui existant. Voir la documentation concat pour le confirmer.
Donc, si vous êtes très préoccupé par l'efficacité, vous devez utiliser la méthode concat lors de la concaténation de chaînes éventuellement vides, et utiliser + sinon. Cependant, la différence de performances devrait être négligeable et vous ne devriez probablement jamais vous en soucier.
la source
String
- comme vous le dites,concat
a une exception lorsque vous concatérez un videString
.J'ai exécuté un test similaire à @marcio mais avec la boucle suivante à la place:
Juste pour faire bonne mesure, je l'ai également ajouté
StringBuilder.append()
. Chaque test a été exécuté 10 fois, avec 100 000 répétitions pour chaque série. Voici les résultats:StringBuilder
gagne haut la main. Le résultat de l'horloge était de 0 pour la plupart des descentes et le plus long a pris 16 ms.a += b
prend environ 40000 ms (40 s) pour chaque exécution.concat
ne nécessite que 10000 ms (10 s) par cycle.Je n'ai pas encore décompilé la classe pour voir les éléments internes ou l'exécuter via le profileur, mais je soupçonne que je
a += b
passe beaucoup de temps à créer de nouveaux objetsStringBuilder
puis à les reconvertirString
.la source
+
est utilisé pour deux chaînes, y a-t-il des cas où l'utilisationStringBuilder
est meilleure que ce serait le casString.valueOf(s1).concat(s2)
? Une idée de la raison pour laquelle les compilateurs n'utiliseraient pas ce dernier [ou omettraient l'valueOf
appel dans les cas où l's1
on sait qu'ils ne sont pas nuls]?La plupart des réponses proviennent de 2008. Il semble que les choses ont changé au fil du temps. Mes derniers benchmarks réalisés avec JMH montrent que sur Java 8
+
est environ deux fois plus rapide queconcat
.Ma référence:
Résultats:
la source
String
n'a jamais inclus de fonction statique pour former une chaîne en concaténant les éléments de aString[]
. Utiliser+
pour concaténer 8 chaînes en utilisant une telle fonction nécessiterait la construction et l'abandon ultérieurString[8]
, mais ce serait le seul objet qui devrait être construit abandonné, tandis que l'utilisation d'unStringBuilder
nécessiterait la construction et l'abandon d'uneStringBuilder
instance et d' au moins unchar[]
magasin de sauvegarde.String.join()
méthodes statiques ont été ajoutées dans Java 8, en tant que wrappers de syntaxe rapide autour de lajava.util.StringJoiner
classe.+
changé pour utiliser de telles fonctions?+
pour l'utiliser) nécessiterait plus que ce que les développeurs Java sont prêts à changer, malheureusement.Tom a raison de décrire exactement ce que fait l'opérateur +. Il crée un temporaire
StringBuilder
, ajoute les pièces et se termine partoString()
.Cependant, jusqu'à présent, toutes les réponses ignorent les effets des optimisations d'exécution HotSpot. Plus précisément, ces opérations temporaires sont reconnues comme un modèle commun et sont remplacées par un code machine plus efficace au moment de l'exécution.
@marcio: Vous avez créé un micro-benchmark ; avec les JVM modernes, ce n'est pas un moyen valide de profiler le code.
La raison pour laquelle l'optimisation de l'exécution est importante est que bon nombre de ces différences de code - y compris la création d'objets - sont complètement différentes une fois que HotSpot démarre. La seule façon de savoir avec certitude est de profiler votre code in situ .
Enfin, toutes ces méthodes sont en fait incroyablement rapides. Cela pourrait être un cas d'optimisation prématurée. Si vous avez du code qui concatène beaucoup de chaînes, la façon d'obtenir la vitesse maximale n'a probablement rien à voir avec les opérateurs que vous choisissez et à la place l'algorithme que vous utilisez!
la source
Que diriez-vous de quelques tests simples? Utilisé le code ci-dessous:
"a + b"
version exécutée en 2500ms .a.concat(b)
exécuté en 1200ms .Testé plusieurs fois. L'
concat()
exécution de la version a pris la moitié du temps en moyenne.Ce résultat m'a surpris car la
concat()
méthode crée toujours une nouvelle chaîne (elle retourne un "new String(result)
". Il est bien connu que:Pourquoi le compilateur n'était-il pas capable d'optimiser la création de chaînes dans le code "a + b", sachant que cela aboutissait toujours à la même chaîne? Cela pourrait éviter une nouvelle création de chaîne. Si vous ne croyez pas la déclaration ci-dessus, testez par vous-même.
la source
Fondamentalement, il existe deux différences importantes entre + et la
concat
méthode.Si vous utilisez la méthode concat , vous ne pourrez concaténer des chaînes que dans le cas de l' opérateur + , vous pouvez également concaténer la chaîne avec n'importe quel type de données.
Par exemple:
Dans ce cas, la sortie doit être 10Hello .
Dans le cas ci-dessus, vous devez fournir deux chaînes obligatoires.
La deuxième et principale différence entre + et concat est que:
Cas 1: Supposons que je concatende les mêmes chaînes avec l' opérateur concat de cette manière
Dans ce cas, le nombre total d'objets créés dans le pool est de 7 comme ceci:
Cas 2:
Maintenant, je vais concaténer les mêmes chaînes via l' opérateur +
Dans le cas ci-dessus, le nombre total d'objets créés n'est que de 5.
En fait, lorsque nous concaténons les chaînes via l' opérateur + , il maintient une classe StringBuffer pour effectuer la même tâche comme suit: -
De cette façon, il ne créera que cinq objets.
Donc, les gars, ce sont les différences de base entre + et la méthode concat . Prendre plaisir :)
la source
String s="I"+"am"+"good"+"boy"; String s2 = "go".concat("od"); System.out.println(s2 == s2.intern());
imprimetrue
, ce qui signifie qu'il"good"
n'était pas dans le pool de chaînes avant d'appelerintern()
Par souci d'exhaustivité, je voulais ajouter que la définition de l'opérateur '+' peut être trouvée dans le JLS SE8 15.18.1 :
À propos de l'implémentation, le JLS dit ce qui suit:
Donc, à en juger par «un compilateur Java peut utiliser la classe StringBuffer ou une technique similaire pour réduire», différents compilateurs peuvent produire différents octets-code.
la source
L' opérateur + peut fonctionner entre une chaîne et une valeur de type de données chaîne, char, entier, double ou flottant. Il convertit simplement la valeur en sa représentation sous forme de chaîne avant la concaténation.
L' opérateur concat ne peut être effectué que sur et avec des chaînes. Il vérifie la compatibilité des types de données et génère une erreur s'ils ne correspondent pas.
Sauf ceci, le code que vous avez fourni fait la même chose.
la source
Je ne pense pas.
a.concat(b)
est implémenté dans String et je pense que l'implémentation n'a pas beaucoup changé depuis les premières machines java. L'+
implémentation de l'opération dépend de la version Java et du compilateur.+
Est actuellement mis en œuvre en utilisantStringBuffer
pour rendre l'opération aussi rapide que possible. Peut-être qu'à l'avenir, cela va changer. Dans les versions précédentes de Java+
, le fonctionnement sur Strings était beaucoup plus lent car il produisait des résultats intermédiaires.Je suppose que cela
+=
est mis en œuvre en utilisant+
et optimisé de manière similaire.la source
Lorsque vous utilisez +, la vitesse diminue à mesure que la longueur de la chaîne augmente, mais lorsque vous utilisez concat, la vitesse est plus stable, et la meilleure option est d'utiliser la classe StringBuilder qui a une vitesse stable pour ce faire.
Je suppose que vous pouvez comprendre pourquoi. Mais la meilleure façon de créer de longues chaînes est d'utiliser StringBuilder () et append (), l'une ou l'autre vitesse sera inacceptable.
la source