web-dev-qa-db-fra.com

Comment puis-je effacer ou vider un StringBuilder?

J'utilise un StringBuilder dans une boucle et toutes les x itérations que je veux vider et commencer par un StringBuilder vide, mais je ne peux voir aucune méthode semblable au .NET - StringBuilder.Clear dans la documentation, uniquement la méthode delete qui semble excessivement compliquée.

Alors, quel est le meilleur moyen de nettoyer une StringBuilder en Java?

572
Hans Olsson

Deux manières qui fonctionnent:

  1. Utilisez stringBuilderObj.setLength(0).
  2. Allouez un nouveau avec new StringBuilder() au lieu d'effacer le tampon.
681
Marcus Frödin

Il existe essentiellement deux alternatives, utilisant setLength(0) pour réinitialiser le constructeur de chaînes ou en créant un nouveau à chaque itération. Les deux peuvent avoir des avantages et des inconvénients en fonction de l'utilisation.

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

Si 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 nouveau 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é requise après quelques itérations et aucune copie ne sera effectuée par la suite.

286
Jörn Horstmann

delete n'est pas trop compliqué:

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

Vous pouvez aussi faire:

myStringBuilder.setLength(0);
71
krtek

Si vous examinez le code source d'un StringBuilder ou StringBuffer, l'appel setLength () réinitialise simplement une valeur d'index pour le tableau de caractères. IMHO utilisant la méthode setLength sera toujours plus rapide qu'une nouvelle allocation. Ils auraient dû nommer la méthode 'clear' ou 'reset' pour que ce soit plus clair.

28
Javamann

Je voterai pour sb.setLength(0); non seulement parce que c'est un appel de fonction, mais car il ne copie pas le tableau dans un autre tableau comme sb.delete(0, builder.length());. Il suffit de remplir les caractères restants à 0 et de définir la variable de longueur à la nouvelle longueur.

Vous pouvez consulter leur implémentation pour valider mon point de ici à la fonction setLength et à la fonction delete0.

18
Ahmed Hegazy

Vous devez utiliser sb.delete(0, sb.length()) ou sb.setLength(0) et NE PAS créer un nouveau StringBuilder ().

Voir ce billet sur la performance: Est-il préférable de réutiliser un StringBuilder dans une boucle?

6
Tony Meng
StringBuilder s = new StringBuilder();
s.append("a");
s.append("a");
// System.out.print(s); is return "aa"
s.delete(0, s.length());
System.out.print(s.length()); // is return 0

est le moyen facile.

4
javaddroid

Si la performance est la préoccupation principale ... l'ironie (IMO) est la construction Java pour formater le texte qui va dans le tampon va prendre beaucoup plus de temps sur le processeur que le alloc/realloc/garbage collection ... eh bien, peut-être pas le GC en fonction du nombre de générateurs que vous créez et ignorez.

Mais ajouter simplement une chaîne composée ("Hello World of" + 6E9 + "earthlings.") À la mémoire tampon rendra probablement la question sans importance.

Et vraiment, si StringBuilder est impliqué, le contenu est complexe, long et plus long qu'un simple String str = "Hi"; (peu importe Java utilise probablement un générateur en arrière-plan de toute façon).

Personnellement, j'essaie de ne pas abuser du GC. Donc, si c'est quelque chose qui va être beaucoup utilisé dans un scénario de tir rapide - comme, par exemple, l'écriture de messages de sortie de débogage ... Je suppose juste de le déclarer ailleurs et de le mettre à zéro pour le réutiliser.

class MyLogger {
    StringBuilder strBldr = new StringBuilder(256);

    public LogMsg( String stuff ) {

        strBldr.setLength(0);

        // ... prepend status level
        strBldr.append("Info");
        // ... prepend timestamp
        strBldr.append(" " + getTimestamp());
        // ... user msg
        strBldr.append(":" + msg);

        log.write(strBldr.toString());
    }
}
2
DevByStarlight

Je pense que beaucoup de réponses ici peuvent manquer une méthode de qualité incluse dans StringBuilder: .delete(int start, [int] end). Je sais que c'est une réponse tardive; cependant, cela devrait être annoncé (et expliqué un peu plus à fond).

Supposons que vous ayez une table StringBuilder - que vous souhaitez modifier, de manière dynamique, tout au long de votre programme (une table sur laquelle je travaille actuellement le fait), par exemple.

StringBuilder table = new StringBuilder();

Si vous parcourez la méthode et modifiez le contenu, utilisez-le, puis souhaitez le supprimer pour "nettoyer" la StringBuilder lors de la prochaine itération, vous pouvez supprimer son contenu, par exemple.

table.delete(int start, int end). 

start et end sont les index des caractères que vous souhaitez supprimer. Vous ne connaissez pas la longueur en caractères et souhaitez supprimer le tout?

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

MAINTENANT, pour le kicker. StringBuilders, comme mentionné précédemment, prend beaucoup de temps en cas de modification fréquente (et peut entraîner des problèmes de sécurité en ce qui concerne le filetage); par conséquent, utilisez StringBuffer - identique à StringBuilder (à quelques exceptions près) - si votre StringBuilder est utilisé à des fins d'interface avec l'utilisateur.

2
Thomas