719 votes

Comment puis-je vider ou effacer un StringBuilder ?

Je suis en train d'utiliser un StringBuilder dans une boucle et à chaque x itérations je veux le vider et recommencer avec un StringBuilder vide, mais je ne vois aucune méthode similaire à la méthode StringBuilder.Clear de .NET dans la documentation, seulement la méthode delete qui semble trop compliquée.

Alors quel est le meilleur moyen de vider un StringBuilder en Java?

913voto

Marcus Points 2317

Deux façons de faire fonctionner:

  1. Utilisez stringBuilderObj.setLength(0).
  2. Allouez-en une nouvelle avec new StringBuilder() au lieu d'effacer le tampon. Notez que pour les chemins de code critiques en termes de performances, cette approche peut être significativement plus lente que l'approche basée sur setLength (puisque un nouvel objet avec un nouveau tampon doit être alloué, l'ancien objet devient éligible pour GC, etc.).

0 votes

Pas trop inquiet pour les performances à moins que ce ne soit une énorme différence, tant que je le fais d'une manière qui ne laissera pas les futurs développeurs se demander pourquoi je l'ai fait d'une certaine manière, je suis content.

12 votes

Vous pouvez laisser un petit commentaire si vous avez peur que les futurs développeurs ne comprennent pas

0 votes

@ho1: De plus, je pense que la réallocation est plus claire que d'utiliser la méthode de suppression avec les deux indices, mais c'est probablement une question de préférence.

312voto

Jörn Horstmann Points 18118

Il y a essentiellement deux alternatives, utiliser setLength(0) pour réinitialiser le StringBuilder ou en créer un nouveau à chaque itération. Les deux peuvent avoir des avantages et des inconvénients selon l'utilisation.

Si vous connaissez à l'avance la capacité attendue du StringBuilder, en créer un nouveau à chaque fois devrait être aussi rapide que de définir une nouvelle longueur. Cela aidera également le ramasse-miettes, car chaque StringBuilder aura une durée de vie relativement courte et le gc est optimisé pour cela.

Lorsque vous ne connaissez pas la capacité, réutiliser le même StringBuilder peut être plus rapide. Chaque fois que vous dépassez la capacité lors de l'ajout, un nouvel tableau de sauvegarde doit être alloué et le contenu précédent doit être copié. En réutilisant le même StringBuilder, il atteindra la capacité nécessaire après quelques itérations et il n'y aura plus de copie par la suite.

1 votes

Merci, j'avais oublié le constructeur avec le paramètre de capacité.

0 votes

Si vous utilisez setLength(0), cela signifie-t-il qu'il garde le tampon interne à sa longueur actuelle? Mon inquiétude est que je ne veux pas new un nouveau StringBuffer parce que je m'attends à ce que parfois j'aie des chaînes assez longues, et donc je commence avec une taille de tampon assez grande (4k ou 32k). Il semble donc que ce serait plus rapide de fixer la longueur à 0. MAIS - si l'espace alloué par StringBuffer ne diminue jamais, je pourrais manquer de mémoire (c'est sous Android où la mémoire peut être limitée).

1 votes

@Michael: Oui, le tampon interne est conservé à sa longueur actuelle. Vous pouvez trouver l'implémentation réelle pour Android à android.googlesource.com/platform/libcore/+/master/luni/src/‌​…. Une fois que vous avez fini d'ajouter des caractères, vous pouvez utiliser la méthode trimToSize pour libérer de l'espace inutile.

80voto

krtek Points 15497

supprimer n'est pas trop compliqué :

myStringBuilder.delete(0, myStringBuilder.length());

Vous pouvez également faire :

myStringBuilder.setLength(0);

1 votes

Compliqué est probablement le mauvais mot, je voulais dire plutôt que ça n'a pas l'air aussi soigné.

0 votes

Mais pas extrêmement efficient par rapport à effectuer une nouvelle allocation.

4 votes

C'est pourquoi j'ai ajouté la version setLength(0), qui devrait être plus rapide. Mais probablement qu'une nouvelle allocation sera plus rapide.

33voto

Javamann Points 1937

Si vous regardez le code source d'un StringBuilder ou StringBuffer, l'appel à setLength() réinitialise simplement une valeur d'index pour le tableau de caractères. À mon avis, l'utilisation de la méthode setLength sera toujours plus rapide qu'une nouvelle allocation. Ils auraient dû nommer la méthode 'clear' ou 'reset' pour qu'elle soit plus claire.

4 votes

@FrankHarper : seulement si vous étendez la chaîne. Si vous la réduisez, Javamann a raison.

0 votes

@FrankHarper Vous avez tort. La source ne fait rien lorsque newLength est zéro.

0 votes

De plus, setLength entraîne également des fuites de mémoire, mais vous le découvrirez bien trop tard. Les gens de SO peuvent parfois donner des réponses vraiment stupides. setLength ne fait rien d'autre que de définir la longueur à zéro. Les allocations restantes sont toujours là. Cette réponse découle de la longueur javascript = 0 pour les tableaux, qui effectue une opération magique pour marquer le tableau comme réutilisable, mais même là, je ne suis pas sûr, et je ne lui fais pas confiance. Le tableau sous-jacent ne sera jamais collecté par le ramasse-miettes.

5voto

javaddroid Points 71
StringBuilder s = new StringBuilder();
s.append("a");
s.append("a");
// System.out.print(s); retourne "aa"
s.delete(0, s.length());
System.out.print(s.length()); // retourne 0

est le moyen facile.

9 votes

Pourquoi pensez-vous que c'est la meilleure façon ? Pour moi, ça a l'air plus moche que la variante setLength(0).

1 votes

L'appel à la suppression vous permet de supprimer une sous-chaîne de l'objet StringBuilder ; tandis que setLength(0) ou setLength(n) vous permet simplement de modifier la capacité de l'objet StringBuilder. En d'autres termes, les deux fonctionnent bien pour une suppression complète, mais delete() a plus de fonctionnalités.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X