60 votes

Assemblage de chaînes par StringBuilder vs StringWriter et PrintWriter

J'ai récemment rencontré un idiome je n'ai pas vu avant: chaîne d'assemblage par StringWriter et PrintWriter. Je veux dire, je sais comment les utiliser, mais j'ai toujours utilisé des StringBuilder. Est-il une raison concrète pour préférer l'un sur l'autre? La méthode StringBuilder semble beaucoup plus naturel pour moi, mais c'est juste le style?

J'ai regardé plusieurs questions (y compris celle qui vient le plus proche: StringWriter ou StringBuilder ), mais aucun dans laquelle les réponses réellement répondre à la question de savoir s'il y a une raison de préférer l'un sur l'autre pour la simple chaîne de montage.

C'est le langage que j'ai vu et utilisé de nombreuses fois: chaîne d'assemblage par StringBuilder:


    public static String newline = System.getProperty("line.separator");
    public String viaStringBuilder () {
       StringBuilder builder = new StringBuilder();
       builder.append("first thing").append(newline);  // NOTE: avoid doing builder.append("first thing" + newline);
       builder.append("second thing".append(newline);
       // ... several things
       builder.append("last thing".append(newline);
       return builder.toString();
    }

Et c'est le nouveau langage: chaîne d'assemblage par StringWriter et PrintWriter:


    public String viaWriters() {
       StringWriter stringWriter = new StringWriter();
       PrintWriter printWriter = new PrintWriter(stringWriter);
       printWriter.println("first thing");
       printWriter.println("second thing");
       // ... several things
       printWriter.println("last thing");
       printWriter.flush();
       printWriter.close();
       return stringWriter.toString();
    }

Edit Il semble qu'il n'y a pas de béton raison de préférer l'un sur l'autre, j'ai donc accepté la réponse qui correspond le mieux à ma compréhension, et de +1ed toutes les autres réponses. En outre, j'ai posté une réponse de ma propre, donnant les résultats de l'analyse comparative que j'ai couru, en réponse à l'une des réponses. Merci à tous.

Éditer à nouveau , Il s'avère qu'il y est une raison concrète de préférer l'un (en particulier le StringBuilder) sur l'autre. Ce que j'ai raté la première fois a été l'ajout de la nouvelle ligne. Lorsque vous ajoutez un saut de ligne (comme ci-dessus, en tant que distinct append), il est légèrement plus rapide - pas énormement, mais couplé avec la clarté d'intention, c'est certainement mieux. Voir ma réponse ci-dessous pour l'amélioration des timings.

43voto

Alan Moore Points 39365

StringWriter est ce que vous utilisez lorsque vous voulez écrire dans une chaîne, mais que vous travaillez avec une API qui attend un enregistreur ou un flux. Ce n'est pas une alternative, c'est un compromis: vous utilisez StringWriter uniquement lorsque vous devez le faire.

20voto

CPerkins Points 5209

Bon, puisque les réponses semblent mettre l'accent sur la stylistique des raisons de préférer l'un sur l'autre, j'ai décidé de gen en place d'un test de chronométrage.

Edit: Suite à robinst du commentaire ci-dessus, j'ai maintenant trois méthodes: l'une qui ne PrintWriter(StringWriter)-style de ajoutant des, et de deux, qui utiliser StringBuilder: l'un avec l'ajout de la nouvelle ligne à l'intérieur de l'append (comme dans l'original: builder.append(thing + newline);), et l'autre n'est séparé append (comme ci-dessus: builder.append(thing).append(newline);).

J'ai suivi mes étalonnage habituel schéma: appeler les méthodes de plusieurs (1000 dans ce cas) la première fois pour donner l'optimiseur de temps à se réchauffer, puis appeler un grand nombre de fois (de 100 000 dans ce cas) en alternance, de sorte que les changements dans le poste de travail de l'environnement d'exécution sont réparties plus équitablement, et exécutez le test lui-même plusieurs fois et la moyenne des résultats.

Oh, et bien entendu, le nombre de lignes créées et de la longueur des lignes est aléatoire, mais a tenu à être le même pour chaque paire d'appels, parce que je voulais éviter d'éventuels effets de la taille de la mémoire tampon ou de la ligne de taille sur les résultats.

Le code est ici: http://pastebin.com/vtZFzuds

Note: je n'ai pas encore mis à jour le pastebin code afin de refléter le nouveau test.

TL,DR? La moyenne des résultats obtenus pour 100 000 appels pour chaque méthode sont assez proches:

  • 0.11908 ms par appel à l'aide de StringBuilder (+saut de ligne à l'intérieur de la parenthèse)
  • 0.10201 ms par appel à l'aide de StringBuilder (saut de ligne distinct append)
  • 0.10803 ms par appel à l'aide de PrintWriter(StringWriter)

C'est tellement étroit que le timing est presque sans importance pour moi, donc je vais continuer à faire les choses de la façon dont je l'ai toujours fait: StringBuilder(séparés d'ajouter des), pour des raisons de style. Bien sûr, tout en travaillant dans cette maturité de la base de code, je vais surtout garder à l'conventions existantes, afin de minimiser la surprise.

20voto

Stephen C Points 255558

Stylistiquement, l' StringBuilder approche est plus propre. Il est de moins en moins de lignes de code et est à l'aide d'une classe qui a été spécialement conçu pour le but de construire des chaînes de caractères.

L'autre considération est qui est plus efficace. La meilleure façon de répondre qui serait à comparer les deux solutions. Mais il y a quelques claire de pointeurs qui StringBuilder devrait être plus rapide. Pour commencer, un StringWriter utilise un StringBuilder StringBuffer sous le capot pour contenir les caractères écrits dans le "stream".

16voto

krock Points 13537

Les écrivains - PrintWriter écrit à un ruisseau. Il fait des choses bizarres, comme la suppression de IOExceptions. Système.est un de ces. - StringWriter est un Écrivain qui écrit pour un StringBuffer (similaire à ByteArrayOutputStream pour OutputStreams)

StringBuilder - et bien sûr StringBuilder est ce que vous voulez si vous voulez simplement des constructions de chaînes dans la mémoire.

Conclusion

Les écrivains de par leur conception, sont censées pousser personnage de données d'un flux de données (généralement un fichier ou par le biais d'une connexion) afin de pouvoir les utiliser Écrivains à simplement assembler des chaînes semble être un peu un effet secondaire.

StringBuilder (et son synchronisé frère StringBuffer) sont conçus pour assembler des chaînes de caractères (lire la chaîne bashing). Si vous regardez le StringBuilder API , vous pouvez voir thatnot seulement pouvez-vous faire en ajoutant de la vanille, mais aussi de remplacer, de le renverser, insert, etc. StringBuilder est votre Chaîne de construction ami.

7voto

pjbarnes Points 41

Je vois deux avantages de la méthode PrintWriter: (1) Il n’est pas nécessaire d’ajouter "+ newline" à la fin de chaque ligne, ce qui entraîne un code plus court si vous avez beaucoup à écrire. (2) Vous n'avez pas besoin d'appeler System.getProperty (); vous laissez le PrintWriter s’inquiéter de ce que devrait être le caractère de nouvelle ligne.

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