字符串是不可变的,这意味着,一旦创建它们就无法更改。

那么,这是否意味着如果你用+ =附加东西比你创建一个StringBuffer并附加文本那么需要更多的内存?

如果使用+ =,每次必须保存在内存中时都会创建一个新的“对象”,不是吗?

有帮助吗?

解决方案

是的,每次用+ =创建一个新对象。然而,这并不意味着它总是错误的做法。这取决于您是否希望将该值作为字符串,或者您是否只是使用它来进一步构建字符串。

如果您实际希望 x + y 的结果为字符串,那么您也可以使用字符串连接。但是,如果你真的要(比方说)循环并附加另一个字符串和另一个字符串等 - 只需要将结果作为字符串放在最后,那么StringBuffer / StringBuilder就是你要走的路。实际上,循环确实是StringBuilder在字符串连接上得到回报的结果 - 5个甚至10个直接连接的性能差异将非常小,但是对于数千个,它变得更糟 - 基本上因为你得到了O(N 2 )串联与StringBuilder的O(N)复杂性的复杂性。

在Java 5及以上版本中,你基本上应该使用StringBuilder - 它是不同步的,但这几乎总是好的;想要在线程之间共享一个是非常罕见的。

我有一个有关所有这些内容的文章,您可能会觉得这些内容很有用。

其他提示

经验法则很简单:

如果您在循环中运行连接,请不要使用 + =

如果您在循环中运行连接,则使用 + = 无关紧要。 (除非是性能关键应用程序

在Java 5或更高版本中,StringBuffer是线程安全的,因此除非您需要,否则您应该支付一些开销。 StringBuilder具有相同的API,但不是线程安全的(即,您只应在单个线程内部使用它。)

是的,如果要构建大字符串,使用StringBuilder会更有效。作为API的一部分传递StringBuilder或StringBuffer可能是不值得的。这太混乱了。

我同意上面发布的所有答案,但它会帮助您更多地了解Java的实现方式。 JVM在内部使用StringBuffers来编译String +运算符(来自 StringBuffer Javadoc ):

  

字符串缓冲区由。使用   编译器实现二进制   字符串连接运算符+。对于   例如,代码:

     x = "a" + 4 + "c"
     

编译为相当于:

     x = new StringBuffer().append("a").append(4).append("c")
                           .toString()

同样, x + =“一些新字符串”等同于 x = x +“一些新字符串”。你知道我要去哪儿吗?

如果你正在进行很多String连接,使用StringBuffer会提高你的性能,但是如果你只做几个简单的String连接,Java编译器可能会为你优化它,你不会注意到性能差异

是。字符串是不可变的。偶尔使用,+ =即可。如果+ =操作密集,则应转向StringBuilder。

但是一旦没有对它们的引用,垃圾收集器将最终释放旧字符串

完全。如果线程安全不是问题,您应该使用StringBuilder。

作为旁注:可能有几个String对象使用相同的后备char [] - 例如,每当使用substring()时,都不会创建新的char [],这使得使用它非常有效。

此外,编译器可能会为您做一些优化。例如,如果你这样做

static final String FOO = "foo";
static final String BAR = "bar"; 

String getFoobar() {
  return FOO + BAR; // no string concatenation at runtime
}

如果编译器在内部使用StringBuilder来尽可能地优化字符串连接 - 如果不是将来可能的话,我不会感到惊讶。

我认为它依赖于GC用废弃的字符串来收集内存。 因此,如果对字符串操作进行大量操作,那么使用字符串构建器执行+ =肯定会更快。但对大多数情况来说,这不应该是一个问题。

是的,你会这就是为什么你应该使用StringBuffer来连接很多字符串。

另请注意,从Java 5开始,您大多数时候也应该更喜欢StringBuilder。它只是某种不同步的StringBuffer。

你是正确的,Strings是不可变的,所以如果你在做大量的字符串连接时试图节省内存,你应该使用StringBuilder而不是+ =。

但是,你可能不介意。程序是为人类读者编写的,因此您可以清晰地进行。如果您进行优化非常重要,那么您应首先进行分析。除非你的程序非常重视字符串活动,否则可能会有其他瓶颈。

它不会使用更多内存。是的,创建了新对象,但旧对象被回收。最后,使用的内存量是相同的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top