Compte tenu des 2 toString()
implémentations 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 pourrait ne pas faire de différence, mais à quel moment basculeriez-vous de +
concat à StringBuilder
?
java
performance
string
concatenation
stringbuilder
non séquenceur
la source
la source
StringBuilder
combien de taille allouer à l'avance sinon, si elle manque d'espace, elle devra doubler la taille en créant un nouveauchar[]
tableau puis copiez les données - ce qui est coûteux. Vous pouvez tricher en donnant la taille, puis il n'est pas nécessaire de créer ce tableau - donc si vous pensez que votre chaîne aura environ 100 caractères, vous pouvez définir le StringBuilder à cette taille et il n'aura jamais à se développer en interne.Réponses:
La version 1 est préférable car elle est plus courte et le compilateur la transformera en fait en version 2 - aucune différence de performance que ce soit.
Au point où vous concaténez dans une boucle - c'est généralement lorsque le compilateur ne peut pas se substituer
StringBuilder
par lui-même.la source
To increase the performance of repeated string concatenation, a Java compiler _may_ use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.
Le mot clé peut être . Étant donné que cela est officiellement facultatif (bien que très probablement mis en œuvre), ne devrions-nous pas nous protéger?La clé est de savoir si vous écrivez une seule concaténation en un seul endroit ou si vous l'accumulez au fil du 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 à l'intérieur d'une boucle, utilisez StringBuilder.
Pour clarifier, en supposant que énormeArray contient des milliers de chaînes, code comme ceci:
est une perte de temps et de mémoire par rapport à:
la source
result += s;
(dans le premier exemple)"{a:"+ a + ", b:" + b + ", c: " + c +"}";
Je préfère:
... car il est court et lisible.
Je n'optimiserais pas cela pour la vitesse à moins que vous ne l'utilisiez dans une boucle avec un nombre de répétitions très élevé et que vous ayez mesuré la différence de performance.
Je suis d'accord, si vous devez sortir beaucoup de paramètres, ce formulaire peut devenir déroutant (comme le dit l'un des commentaires). Dans ce cas, je passerais à une forme plus lisible (peut-être en utilisant ToStringBuilder d'apache-commons - tiré de la réponse de matt b) et ignorerais à nouveau les performances.
la source
null
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 pire comme celui-ci:
La sortie est:
Le problème est que + = ajouter à une chaîne reconstruit une nouvelle chaîne, donc cela coûte quelque chose de linéaire à la longueur de vos chaînes (somme des deux).
Donc - à votre question:
La deuxième approche serait plus rapide, mais elle est moins lisible et plus difficile à maintenir. Comme je l'ai dit, dans votre cas particulier, vous ne verriez probablement pas la différence.
la source
+=
, l'exemple d'origine était une séquence de+
, que le compilateur transforme en un seulstring.concat
appel. Vos résultats ne s'appliquent pas.J'ai également eu un conflit avec mon patron sur le fait d'utiliser Append ou + .Comme ils utilisent Append (je n'arrive toujours pas à comprendre comme on dit à chaque fois qu'un nouvel objet est créé). J'ai donc pensé faire de la R & D.Bien que j'aime l'explication de Michael Borgwardt, mais je voulais juste montrer une explication si quelqu'un aurait vraiment besoin de savoir à l'avenir.
et le démontage de la classe ci-dessus se présente comme
À partir des deux codes ci-dessus, vous pouvez voir que Michael a raison. Dans chaque cas, un seul objet SB est créé.
la source
Depuis Java 1.5, la concaténation simple d'une ligne avec "+" et StringBuilder.append () génère exactement le même bytecode.
Donc, pour des raisons de lisibilité du code, utilisez "+".
2 exceptions:
la source
En utilisant la dernière version de Java (1.8), le démontage (
javap -c
) montre l'optimisation introduite par le compilateur.+
ainsisb.append()
va générer un code très similaire. Cependant, il vaudra la peine d'examiner le comportement si nous l'utilisons+
dans une boucle for.Ajouter des chaînes en utilisant + dans une boucle for
Java:
ByteCode :(
for
extrait de boucle)Ajout de chaînes à l'aide de stringbuilder.append
Java:
ByteCdoe :(
for
extrait de boucle)Il y a cependant une différence flagrante . Dans le premier cas, où a
+
été utilisé, nouveauStringBuilder
est créé pour chaque pour l'itération de boucle et le résultat généré est stocké en faisant untoString()
appel (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 enfor
boucle.la source
Dans Java 9, la version 1 devrait être plus rapide car elle est convertie en
invokedynamic
appel. Plus de détails peuvent être trouvés dans JEP-280 :la source
Pour des raisons de performances, l'utilisation de
+=
(String
concaténation) est déconseillée. La raison en est: JavaString
est immuable, chaque fois qu'une nouvelle concaténation est effectuée, une nouvelleString
est créée (la nouvelle a une empreinte digitale différente de l'ancienne déjà dans le pool de chaînes) ). La création de nouvelles chaînes exerce une pression sur le GC et ralentit le programme: la création d'objets coûte cher.Le code ci-dessous devrait le rendre plus pratique et plus clair à la fois.
Les résultats d'une analyse sont présentés ci-dessous.
Ne tenant pas 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): ne jamais utiliser le
+=
pour concaténer des chaînes ensemble, même dans des cas très basiques où quelques concaténations sont nécessaires (comme dit, la création de nouvelles chaînes est de toute façon coûteuse et met la pression sur le GC).la source
Voir l'exemple ci-dessous:
Production:
À mesure que la longueur de chaîne augmente, le temps de concaténation augmente également.
C'est là que le
StringBuilder
besoin est certain.Comme vous le voyez, la concaténation:
UUID.randomUUID()+"---"
n'affecte pas vraiment le temps.PS: Je ne pense pas que quand utiliser StringBuilder en Java est vraiment un doublon de cela.
Cette question parle de la
toString()
plupart du temps qui n'effectue pas de concaténation d'énormes cordes.Mise à jour 2019
Depuis des
java8
temps, les choses ont un peu changé. Il semble que maintenant (java13), le temps de concaténation de+=
soit pratiquement le même questr.concat()
. Cependant, leStringBuilder
temps de concaténation est toujours constant . (Le message d'origine ci-dessus a été légèrement modifié pour ajouter une sortie plus détaillée)Il convient de noter également que la
bytecode:8/java.version:13
combinaison présente un bon avantage en termes de performances par rapport àbytecode:8/java.version:8
la source
java13
qui sont maintenant différents. Mais je pense que la conclusion principale reste la même.Apache Commons-Lang a une classe ToStringBuilder qui est super facile à utiliser. Il fait un bon travail de gestion de la logique d'ajout ainsi que de formatage de l'apparence de votre toString.
Renvoie une sortie qui ressemble
com.blah.YourClass@abc1321f[a=whatever, b=foo]
.Ou sous une forme plus condensée en utilisant le chaînage:
Ou si vous souhaitez utiliser la réflexion pour inclure tous les domaines de la classe:
Vous pouvez également personnaliser le style de la ToString si vous le souhaitez.
la source
Rendez la méthode toString aussi lisible que possible!
La seule exception pour cela dans mon livre est si vous pouvez me prouver qu'il consomme des ressources importantes :) (Oui, cela signifie un 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 "+", ces améliorations et celles à venir sont gratuites.
la source
Il semble y avoir un débat sur l'utilisation de StringBuilder avec les compilateurs actuels. J'ai donc pensé donner mes 2 cents d'expérience.
J'ai un
JDBC
ensemble de résultats de 10 000 enregistrements (oui, j'ai besoin de tous en un seul lot.) L'utilisation de l'opérateur + prend environ 5 minutes sur ma machine avecJava 1.8
. L'utilisationstringBuilder.append("")
prend moins d'une seconde pour la même requête.La différence est donc énorme. À l'intérieur d'une boucle
StringBuilder
est beaucoup plus rapide.la source
La concaténation de String en termes de performances en utilisant '+' est plus coûteuse car elle doit faire une toute nouvelle copie de String car les Strings sont immuables en Java. Cela joue un rôle particulier si la concaténation est très fréquente, par exemple: à l'intérieur d'une boucle. Voici ce que mon IDEA suggère lorsque j'essaie de faire une telle chose:
Règles générales:
Voici un joli blog Jon Skeet sur ce sujet.
la source
Puis-je souligner que si vous allez parcourir une collection et utiliser StringBuilder, vous voudrez peut-être consulter Apache Commons Lang et StringUtils.join () (dans différentes )?
Quelles que soient les performances, cela vous évitera de créer des StringBuilders et des boucles pour ce qui semble être la millionième fois.
la source
Voici ce que j'ai vérifié en Java8
Utilisation de StringBuilder
la source
Je pense que nous devrions aller avec l'approche append StringBuilder. Raison d'être :
La concaténation de chaîne créera un nouvel objet chaîne à chaque fois (comme la chaîne est un objet immuable), elle créera donc 3 objets.
Avec le générateur de chaînes, un seul objet sera créé [StringBuilder est mutable] et la chaîne supplémentaire y est ajoutée.
la source
Pour les cordes simples comme ça, je préfère utiliser
Dans l'ordre, je dirais que la méthode préférée de construction d'une chaîne utilise StringBuilder, String # concat (), puis l'opérateur surchargé +. StringBuilder est une augmentation significative des performances lorsque le travail de grandes chaînes, tout comme l'utilisation de l'opérateur +, est une diminution importante des performances (diminution exponentielle à mesure que la taille de la chaîne augmente). Le seul problème avec l'utilisation de .concat () est qu'il peut lever des NullPointerExceptions.
la source