StringBuilder与StringWriter和PrintWriter的字符串汇编

CPe*_*ins 54 java

我最近遇到了一个我以前没见过的成语:StringWriter和PrintWriter的字符串汇编.我的意思是,我知道如何使用它们,但我一直使用StringBuilder.是否有一个具体的理由选择一个而不是另一个?StringBuilder方法对我来说似乎更自然,但它只是风格吗?

我在这里看了几个问题(包括最近的一个问题:StringWriter或StringBuilder),但没有一个问题的答案实际上解决的问题是,是否有理由优先选择一个而不是简单的字符串汇编.

这是我见过并习惯了很多次的成语: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();
    }
Run Code Online (Sandbox Code Playgroud)

这是新的成语:StringWriter和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();
    }
Run Code Online (Sandbox Code Playgroud)

编辑似乎没有具体的理由偏爱其中一个,所以我接受了最符合我理解的答案,并且+ 1除了所有其他答案.另外,我发布了自己的答案,给出了我运行的基准测试结果,以回答其中一个答案.谢谢大家.

再次编辑事实证明,有一个具体的理由,更喜欢一个(特别是StringBuilder的)比其他.我第一次错过的是添加换行符.当你添加一个换行符(如上所述,作为一个单独的追加)时,它会稍微快一点 - 不是很大,但加上意图的清晰度,它肯定会更好.请参阅下面的答案,了解改进的时间安排.

Ala*_*ore 39

StringWriter是您在要写入字符串时使用的,但是您正在使用期望Writer或Stream的API.它不是替代品,它是一种妥协:只有在必要时才使用StringWriter.

  • 这应该是这个问题的公认答案.我实际上遇到过一种情况,我被迫使用StringWriter,因为API(第三方API)需要Writer实例,而我只是想将内容写入字符串而不是文件/ stdout.@Alan简单地将其钉在了他说的时候"必要的时候使用StringWriter". (3认同)
  • 我遇到过一个我不得不使用`StringWriter`的场景,因为API _of_ _the_` java.lang.Throwable` _class_没有任何方法在异常的堆栈跟踪时接收`StringBuilder`作为参数必须打印(只有接受[`PrintStream`]的方法(http://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html#printStackTrace%28java.io. PrintStream%29)或[`PrintWriter`](http://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html#printStackTrace%28java.io.PrintWriter%29)). (2认同)

CPe*_*ins 19

好吧,既然答案似乎强调了偏爱一方的风格原因,我决定进行时间测试.

编辑:按照上面robinst的评论,我现在有三种方法:一是它确实为PrintWriter(StringWriter的)风格的附加,而其中两个使用StringBuilder(原为:一个换行符的追加追加内builder.append(thing + newline);),以及其他人做一个单独的追加(如上所述:) builder.append(thing).append(newline);.

我遵循我通常的基准测试方案:首先调用几个方法(在这种情况下为1000),以便优化器有时间预热,然后按交替顺序多次调用每次(在这种情况下为100,000),以便进行任何更改在工作站的运行时环境中,分布更加公平,并多次运行测试本身并对结果进行平均.

哦,当然,创建的行数和行的长度是随机的,但对于每对调用都保持相同,因为我想避免缓冲区大小或行大小对结果产生任何可能的影响.

代码如下:http://pastebin.com/vtZFzuds

注意:我还没有更新pastebin代码以反映新测试.

TL,DR? 每种方法100,000次调用的平均结果非常接近:

  • 使用StringBuilder每次调用0.11908 ms(在paren内部使用+换行符)
  • 使用StringBuilder每次调用0.10201 ms(换行作为单独的附加)
  • 使用PrintWriter(StringWriter)每次调用0.10803 ms

那是如此接近以至于时间几乎与我无关,所以我将继续按照我一直以来的方式做事:StringBuilder(带有单独的附加),出于文体原因.当然,在这个既定且成熟的代码库中工作时,我将主要遵循现有的约定,以尽量减少意外.


Ste*_*n C 18

在风格上,这种StringBuilder方法更清洁.代码行数较少,并且使用专门为构建字符串而设计的类.

另一个考虑因素是更有效率.回答这个问题的最佳方法是对两种替代方案进行基准测试.但是有一些明确的指示,StringBuilder 应该更快.首先,StringWriter使用StringBuilder StringBuffer来保存写入"stream"的字符.


kro*_*ock 14

作家 - PrintWriter写入流.它做了一些奇怪的事情,比如压制IOExceptions.System.out就是其中之一. - StringWriter是一个写入StringBuffer的Writer(类似于OutputStreams的ByteArrayOutputStream)

StringBuilder - 当然,如果你只是想在内存中构造字符串,那么StringBuilder就是你想要的.

结论

设计的作者是为了将字符数据推出流(通常是文件或通过连接),因此能够使用Writers简单地组装字符串似乎有点副作用.

StringBuilder的(和它的同步兄弟的StringBuffer)被设计来组装字符串(字符串读扑).如果您查看StringBuilder API,您可以看到,您不仅可以执行vanilla附加,还可以替换,反向,插入等.CtringBuilder是您的String构建好友.


小智 7

我看到了PrintWriter方法的两个优点:(1)您不必在每一行的末尾添加"+换行符",如果您有大量的写入操作,实际上会导致更短的代码.(2)您不必调用System.getProperty(); 你让PrintWriter担心换行符应该是什么.