Java编译器不自动优化字符串连接?

时间:2012-07-03 12:46:45

标签: java performance optimization jsoup stringbuilder

以下Jsoup代码连接容器els中所有元素的文本:

for (Element el : els)
  entireText += el.text();          

在一个包含~64个元素的容器中,每个元素包含~1KB(整个文本总共约64KB),这个简单的循环在典型的低端Android手机上大约需要 8秒

这种缓慢的性能令我感到惊讶,因为我认为Java编译器会将A + B + C等表达式替换为new StringBuilder(A).append(B).append(C).toString()

情况不是这样吗?

我错过了什么?

2 个答案:

答案 0 :(得分:12)

  

这种缓慢的表现令我惊讶,因为我在...   Java编译器替换A + B + C等表达式的印象   使用新的StringBuilder(A).append(B).append(C).toString()。

因此编译器会创建代码:

for (Element el : els)
  entireText = new StringBuilder(entireText).append(el.text()).toString(); 

您需要在循环外创建StringBuilder并手动附加到它。

答案 1 :(得分:4)

这里的问题是你的第一次迭代会创建一个1k String,第二次创建一个2k String,第三次创建一个3k String,...

每个字符串都需要创建前一个字符串的副本。所以你的第一次迭代复制1k文本,第二次复制2k,第三次复制3k,...

因此每次迭代都比前一次迭代慢,最后一次迭代分配64k缓冲区并复制64k。

使用StringBuilder(如@mlk所示)意味着您只需要分配64k一次(不完全,但足够接近)并且仅复制64k数据(而不是64k + 63k + 62k + 61k) + 60K + ...)。