【问题标题】:Why would you use a StringBuilder method over a String in Java? [duplicate]为什么要在 Java 中对 String 使用 StringBuilder 方法? [复制]
【发布时间】:2021-12-03 04:21:17
【问题描述】:

使用 StringBuilder 方法而不是 String 有什么好处?为什么不直接修改字符串中的内容?

我知道 StringBuilder 是可变的,但是如果您必须编写更多行代码来附加到它上面,为什么不更改原始 String 呢?

如果有人能提供一个 StringBuilder 更有益的例子,我将不胜感激。

【问题讨论】:

  • "为什么不改变原来的字符串?"因为它是不可变的。
  • 它非常依赖于上下文(并且多年来,字符串连接之类的处理方式已经发生了变化)。
  • 我实际上只是使用了字符串生成器,如果您需要从另一个线程或匿名方法访问字符串并且它需要是最终的,它会有所帮助,因此 String 对象变得不可变,即)最终 StringBuilder builder =新的 StringBuilder(); chars.forEach(builder::append);
  • 尝试回答“构建器模式有什么好处?”
  • "为什么不改变原来的字符串?"你不能。字符串不能更改。 (有很多很好的理由。)StringBuilder 或多或少“可以修改的字符串”。

标签: java stringbuilder


【解决方案1】:

您不能更改原始字符串,因为它是不可变的,因此每个操作都像 String s = ""; 一样

s += "something";

创建并重新分配新对象(可能在不久的将来它还会为 GC 增加一点工作)。另一方面,修改StringBuilder(通常)不会创建新对象(实际上,在构建器实例上调用toString() 方法时,它只会在最后发生一次)

因此,当您多次修改字符串(例如在一些长循环中)时,通常使用StringBuilder

过度使用StringBuilder 仍然是常见错误 - 它可能是premature optimization 的示例


另请阅读:

【讨论】:

  • @user16320675 好点!
  • @user16320675:是的,但是“当数组超过某个阈值时调整大小并复制数组”和“为每个操作创建一个数组/字符串的新副本以它”。
  • 在很多情况下虽然java编译器可以优化工作并且不会有太大的区别。我相信在 99% 的情况下不会有差异。因此,对于简单的情况,我认为 string + 可以更具可读性而没有缺点。如果存在复杂的字符串构建,则 stringbuilder 还可以为您提供更好的可读性,这很好。我会更多地考虑代码的简洁性而不是性能
  • @VeselinDavidov: StringBuilder 在循环中构造大字符串时特别需要。在大多数其他情况下,这是不必要的。
【解决方案2】:

通过了解String 类的不变性,您走在了正确的轨道上。

基于 [1] 和 [2],以下是推荐每种实现类型的一些情况:

1。简单的字符串连接

String answer = firstPart + "." + secondPart;

这是语法糖

String answer = new StringBuilder(firstPart).append("."). append(secondPart).toString();

这实际上非常高效,是简单字符串连接的推荐方法 [1]。

2。逐步构建

String answer = firstPart;
answer += ".";
answer += secondPart;

在引擎盖下,这转化为

String answer = new StringBuilder(firstPart).toString(); 
answer = new StringBuilder(answer).append(".").toString(); 
answer = new StringBuilder(answer).append(secondPart).toString();

这会创建一个临时的 StringBuilder 和中间的 String 对象,它们效率低下 [1]。尤其是在不使用中间结果的情况下。

在这种情况下使用StringBuilder

3。用于循环构建和扩展以适应更大的集合

String result = "";

for(int i = 0; i < numItems(); i++) 
  result += lineItem(i);

return result;

上面的代码是 O(n^2),其中 n 是字符串的数量。这是由于 String 类的不变性,以及当连接两个字符串时,两个字符串的内容都会被复制 [2]。

所以对于一些固定长度的项目可能没问题,但它不会缩放。 在这种情况下,请使用StringBuilder

StringBuilder sb = new StringBuilder(numItems() * LINE_SIZE);

for(int i = 0; i < numItems(); i++)
  sb.append(lineItem(i));

return b.toString();

此代码是 O(n) 时间,其中 n 是项目或字符串的数量。 因此,随着字符串数量的增加,您会看到性能上的差异 [2]。

这段代码在StringBuilder的初始化中预先分配了一个数组,但是即使使用默认大小的数组,对于大量项目[2]来说,它也会比之前的代码快很多。

总结

如果您只连接几个字符串或性能不重要(即演示/玩具应用程序),请使用字符串连接。否则,使用StringBuilder 或考虑将字符串处理为字符数组[2]。

参考资料:

[1] Java 性能:Scott Oaks 的权威指南:Link

[2] Joshua Bloch 撰写的有效 Java 第 3 版:Link

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-12
    • 2023-04-04
    • 1970-01-01
    • 2022-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-29
    相关资源
    最近更新 更多