StringBuilder.append链是否比字符串连接更有效?

Mar*_*era 57 java

根据Netbeans的提示名为Use chain of .append方法而不是字符串连接

在StringBuilder或StringBuffer的append方法的调用参数中查找字符串连接.

StringBuilder.append()是否真的比字符串连接更有效?

代码示例

StringBuilder sb = new StringBuilder();
sb.append(filename + "/");
Run Code Online (Sandbox Code Playgroud)

StringBuilder sb = new StringBuilder();
sb.append(filename).append("/");
Run Code Online (Sandbox Code Playgroud)

cor*_*iKa 79

您必须平衡可读性和功能性.

假设您有以下内容:

String str = "foo";
str += "bar";
if(baz) str += "baz";
Run Code Online (Sandbox Code Playgroud)

这将创建2个字符串构建器(您实际上只需要1个)以及临时的附加字符串对象.如果你去,你会更有效率:

StringBuilder strBuilder = new StringBuilder("foo");
strBuilder.append("bar");
if(baz) strBuilder.append("baz");
String str = strBuilder.toString();
Run Code Online (Sandbox Code Playgroud)

但作为一种风格问题,我认为第一个看起来很好.单个对象创建的性能优势对我来说似乎很小.现在,如果不是3个字符串,你有10个,20个或100个,我会说性能超过了风格.如果它是在一个循环中,我肯定会使用字符串构建器,但我认为只需要几个字符串就可以使用"草率"方式使代码看起来更清晰.但是......这里潜藏着一个非常危险的陷阱!请继续阅读(暂停以构建悬念... dun dun dunnnn)

有人说总是使用显式字符串构建器.一个基本原理是你的代码会继续增长,并且它通常会以与现有代码相同的方式进行(也就是说它们不会花时间重构.)所以你最终会得到每个创建的10或20个语句你不需要自己的建设者.因此,为了从一开始就防止这种情况,他们说总是使用显式构建器.

因此,虽然在你的例子中,它不会特别快,当未来的某个人决定他们想要一个文件扩展名,或类似的东西,如果他们继续使用字符串连接而不是StringBuilder,他们会去最终遇到性能问题.

我们还需要考虑未来.假设您在JDK 1.1中重新编写Java代码,并且您有以下方法:

public String concat(String s1, String s2, String s3) {
    return s1 + s2 + s3;
}
Run Code Online (Sandbox Code Playgroud)

那时,它会很慢,因为StringBuilder不存在.

然后在JDK 1.3中,您决定使用StringBuffer使其更快(StringBuilder仍然不存在).你做这个:

public String concat(String s1, String s2, String s3) {
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    sb.append(s3);
    return sb.toString();
}
Run Code Online (Sandbox Code Playgroud)

它变得更快.真棒!

现在JDK 1.5问世了,随之而来的是StringBuilder(比StringBuffer更快)和自动转换

return s1 + s2 + s3;
Run Code Online (Sandbox Code Playgroud)

return new StringBuilder().append(s1).append(s2).append(s3).toString();
Run Code Online (Sandbox Code Playgroud)

但是,由于您明确使用了StringBuffer,因此无法获得此性能优势.因此,通过聪明,当Java变得比你聪明时,你已经造成了性能损失.所以你必须记住,有些事你不会想到.


Dir*_*irk 11

好吧,你的第一个例子基本上由编译器翻译成了一些东西:

StringBuilder sb = new StringBuilder();
sb.append(new StringBuilder().append(filename).append("/").toString());
Run Code Online (Sandbox Code Playgroud)

是的,这里存在一定的低效率.但是,在您的计划中是否真的重要是一个不同的问题.除了有问题的风格(暗示:主观)之外,如果你在紧密循环中这样做,通常也很重要.


Mat*_*ley 7

到目前为止,没有一个答案明确地解决了提示的具体情况.它并不是说总是使用StringBuilder#append而不是连接.但是,如果你已经在使用a StringBuilder,那么在串联中混合是没有意义的,因为它会创建一个冗余StringBuilder(参见Dirk的答案)和一个不必要的临时String实例.

几个答案已经讨论了为什么建议的方法更有效,但重点是,如果你已经有一个StringBuilder实例,只需要调用append它.它是可读的(在我看来,显然是谁写了NetBeans提示),因为你append无论如何都要打电话,而且效率更高一些.

  • 我自己的偏好是诉诸我的主要规则:“做有意义的事情”。在大多数情况下,两种方法都不会造成巨大的性能差异,因此,当连接更清晰并且不太可能显着影响性能时,建议使用级联。在必须在不同的语句中发生多个串联的情况下,我更喜欢`StringBuilder`,但是当它们可以在一个表达式中出现时,我更喜欢这样做。除非字符串很大,否则易读性应该比性能具有更高的优先级。 (2认同)