web-dev-qa-db-fra.com

Java: String concat vs StringBuilder - optimisé, que dois-je faire?

Dans cette réponse , elle indique (implique) que la concaténation de chaînes est de toute façon optimisée dans les opérations de StringBuilder. Par conséquent, lorsque j'écris mon code, existe-t-il une raison pour écrire du code StringBuilder dans le code source? Notez que mon cas d'utilisation est différent de la question du PO, car je concatène/ajoute des centaines de milliers de lignes.

Pour être plus clair: je suis conscient des différences qui existent entre chacune d’elles. C’est juste que je ne sais pas si cela vaut la peine d’écrire du code StringBuilder, car il est moins lisible et lorsque son cousin supposé plus lent, la classe String, est automatiquement converti en le processus de compilation quand même.

44
Soyuz

Je pense que l’utilisation de StringBuilder vs + dépend vraiment du contexte dans lequel vous l’utilisez.

Généralement, en utilisant JDK 1.6 et supérieur, le compilateur joindra automatiquement les chaînes en utilisant StringBuilder.

String one = "abc";
String two = "xyz";
String three = one + two;

Ceci compilera String three en tant que:

String three = new StringBuilder().append(one).append(two).toString();

Ceci est très utile et nous évite un peu d’exécution. Cependant, ce processus n'est pas toujours optimal. Prends pour exemple:

String out = "";
for( int i = 0; i < 10000 ; i++ ) {
    out = out + i;
}
return out;

Si nous compilons en bytecode puis décompilons le bytecode généré, nous obtenons quelque chose comme:

String out = "";
for( int i = 0; i < 10000; i++ ) {
    out = new StringBuilder().append(out).append(i).toString();
}
return out;

Le compilateur a optimisé la boucle interne mais n’a certainement pas fait les meilleures optimisations possibles. Pour améliorer notre code, nous pourrions utiliser:

StringBuilder out = new StringBuilder();
for( int i = 0 ; i < 10000; i++ ) {
    out.append(i);
}
return out.toString();

Ceci est maintenant plus optimal que le code généré par le compilateur, il est donc absolument nécessaire d'écrire du code en utilisant les classes StringBuilder/StringBuffer dans les cas où un code efficace est nécessaire. Les compilateurs actuels ne sont pas très aptes à gérer la concaténation de chaînes dans des boucles, mais cela pourrait changer dans le futur.

Vous devez regarder attentivement pour savoir où vous devez appliquer manuellement StringBuilder et essayer de l'utiliser si cela ne réduit pas non plus la lisibilité de votre code.

Remarque: J'ai compilé le code à l'aide de JDK 1.6 et décompilé le code à l'aide du programme javap, qui crache du code octet. Il est assez facile à interpréter et constitue souvent une référence utile lorsque vous essayez d'optimiser le code. Le compilateur change votre code en coulisses, il est donc toujours intéressant de voir ce qu'il fait!

111
Tom Cammann

La phrase clé de votre question est "soi-disant plus lent". Vous devez déterminer s'il s'agit bien d'un goulot d'étranglement, puis voir lequel est le plus rapide.

Si vous êtes sur le point d'écrire ce code mais que vous ne l'avez pas encore écrit, écrivez ce qui vous paraît le plus clair et, au besoin, voyez s'il s'agit d'un goulot d'étranglement.

Bien qu'il soit logique d'utiliser le code que vous considérez plus rapide, il est préférable de prendre le temps de trouver ce qui est plus rapide quand vous n'en avez pas besoin, c'est une perte de temps. La lisibilité est supérieure aux performances jusqu'à ce que les performances soient inacceptables.

3
jmoreno

Cela dépend du cas, mais on pense que StringBuilder est un peu plus rapide. Si vous effectuez une concaténation à l'intérieur d'une boucle, je vous suggère d'utiliser StringBuilder.

Quoi qu'il en soit, je vous conseillerais de profiler et d'analyser votre code (si vous effectuez un ajout aussi volumineux).

Attention cependant: les instances de StringBuilder sont mutables et ne doivent pas être partagées entre les threads (à moins que vous ne sachiez vraiment ce que vous faites.) Par opposition à String, qui sont immuables.

2
bssstudio

J'ai peut-être mal compris votre question, mais StringBuilder est plus rapide lors de l'ajout de chaînes. Donc, oui, si vous ajoutez des "centaines de milliers de lignes", vous devez absolument utiliser StringBuilder (ou StringBuffer si vous utilisez une application multithread).

(Réponse plus complète dans les commentaires)

0
cldjr