Les chaînes sont immuables - cela signifie que je ne devrais jamais utiliser + = et uniquement StringBuffer?

StackOverflow https://stackoverflow.com/questions/1635659

Question

Les chaînes sont immuables, ce qui signifie qu'une fois créées, elles ne peuvent plus être modifiées.

Alors, cela signifie-t-il qu'il faudrait plus de mémoire si vous ajoutez des éléments avec + = plutôt que de créer un StringBuffer et d'y ajouter du texte?

Si vous utilisez + =, vous créez un nouvel "objet" chaque fois que vous devez enregistrer dans la mémoire, n'est-ce pas?

Était-ce utile?

La solution

Oui, vous allez créer un nouvel objet à chaque fois avec + =. Cela ne signifie pas que ce soit toujours la mauvaise chose à faire, cependant. Cela dépend si vous voulez que cette valeur soit une chaîne ou si vous allez simplement l'utiliser pour construire la chaîne plus avant.

Si vous voulez réellement obtenir le résultat de x + y sous forme de chaîne, vous pouvez également utiliser une concaténation de chaîne. Cependant, si vous voulez vraiment (dire) boucler en rond et ajouter une autre chaîne, et une autre, etc. - n'ayant besoin que du résultat sous forme de chaîne à la toute fin, alors StringBuffer / StringBuilder est la solution. En effet, le bouclage est vraiment le moyen par lequel StringBuilder rapporte de la concaténation de chaînes - la différence de performance pour 5 ou même 10 concaténations directes va être assez petite, mais pour des milliers, elle devient bien pire - essentiellement parce que vous obtenez O (N 2 ) complexité avec concaténation vs complexité O (N) avec StringBuilder.

Dans Java 5 et les versions ultérieures, vous devriez utiliser essentiellement StringBuilder - il n’est pas synchronisé, mais c’est presque toujours correct; il est très rare de vouloir en partager un entre les threads.

J'ai un article sur tout cela qui pourrait vous être utile.

Autres conseils

La règle à suivre est simple:

Si vous exécutez des concaténations dans une boucle, n'utilisez pas + =

Si vous n'utilisez pas les concaténations dans une boucle, utiliser + = n'a pas d'importance. (Sauf si une application critique en termes de performances

Dans Java 5 ou une version ultérieure, StringBuffer est thread-safe, ainsi que des frais généraux que vous ne devriez pas payer sauf si vous en avez besoin. StringBuilder a la même API mais n'est pas thread-safe (c'est-à-dire que vous ne devriez l'utiliser que de manière interne à un seul thread).

Oui, si vous créez des chaînes de grande taille, il est plus efficace d'utiliser StringBuilder. Il ne vaut probablement pas la peine de passer StringBuilder ou StringBuffer dans le cadre de votre API. C'est trop déroutant.

Je suis d’accord avec toutes les réponses mentionnées ci-dessus, mais cela vous aidera un peu à mieux comprendre la manière dont Java est implémenté. La machine virtuelle Java utilise StringBuffers en interne pour compiler l'opérateur String + (à partir de Javadoc de StringBuffer ):

  

Les tampons de chaîne sont utilisés par le   compilateur pour implémenter le binaire   opérateur de concaténation de chaîne +. Pour   Par exemple, le code:

     x = "a" + 4 + "c"
     

est compilé à l'équivalent de:

     x = new StringBuffer().append("a").append(4).append("c")
                           .toString()

De même, x + = "une nouvelle chaîne" équivaut à x = x + "une nouvelle chaîne" . Voyez-vous où je vais avec ça?

Si vous faites beaucoup de concaténations de chaînes, utiliser StringBuffer augmentera vos performances, mais si vous ne faites que quelques concaténations de chaînes simples, le compilateur Java l'optimisera probablement pour vous, et vous ne remarquerez rien. une différence de performance

Oui. String est immuable. Pour une utilisation occasionnelle, + = est OK. Si l'opération + = est intensive, vous devez utiliser StringBuilder.

Mais le ramasse-miettes finira par libérer les anciennes chaînes une fois qu'il n'y aura plus de référence à elles

Exactement. Vous devez cependant utiliser un StringBuilder si la sécurité des threads n'est pas un problème.

Remarque: il se peut que plusieurs objets String utilisent le même support char []. Par exemple, chaque fois que vous utilisez substring (), aucun nouveau caractère [] ne sera créé, ce qui rend son utilisation très efficace.

De plus, les compilateurs peuvent effectuer certaines optimisations à votre place. Par exemple, si vous faites

static final String FOO = "foo";
static final String BAR = "bar"; 

String getFoobar() {
  return FOO + BAR; // no string concatenation at runtime
}

Je ne serais pas surpris que le compilateur utilise StringBuilder en interne pour optimiser la concaténation des chaînes lorsque cela est possible - si ce n'est peut-être déjà à l'avenir.

Je pense que cela dépend du GC pour collecter la mémoire avec la chaîne abandonnée. Donc, faire + = avec le constructeur de chaînes sera certainement plus rapide si vous manipulez beaucoup de chaînes. Mais cela ne devrait pas poser de problème dans la plupart des cas.

Oui, c’est exactement pourquoi vous devriez utiliser StringBuffer pour concaténer beaucoup de chaînes.

Notez également que depuis Java 5, vous devez également préférer StringBuilder la plupart du temps. C'est juste une sorte de StringBuffer non synchronisé.

Vous avez raison de dire que les chaînes sont immuables. Par conséquent, si vous essayez de conserver la mémoire tout en effectuant beaucoup de concaténation de chaînes, utilisez plutôt StringBuilder que + =.

Cependant, cela ne vous dérange pas. Les programmes sont écrits pour leurs lecteurs humains, vous pouvez donc y aller avec clarté. S'il est important d'optimiser, vous devez d'abord profiler. À moins que votre programme ne soit très fortement axé sur l'activité des chaînes, il y aura probablement d'autres goulots d'étranglement.

Non

Il n’utilisera pas plus de mémoire. Oui, de nouveaux objets sont créés, mais les anciens sont recyclés. Au final, la quantité de mémoire utilisée est la même.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top