Java编译器为字符串连接构建低效的代码?

时间:2012-12-03 06:32:59

标签: java performance javac string-concatenation

我认为这是结合字符串的最有效方法

new StringBuilder(s1.length() + s2.length() + s3.length()).append(s1).append(s2).append(s3).toString();

这里创建StringBuilder的缓冲区,其容量足以容纳其中的所有字符串,否则StringBuilder可能需要将缓冲区扩展3次。

但是当我编译/反编译这个

String s4 = s1 + s2 + s3;

我将javac(1.7.0_03)构建的.class中的实际代码作为

String s4 = (new StringBuilder(String.valueOf(s1))).append(s2).append(s3).toString();

哪种方式更有效?

更新

Steven Schlansker建议,这是性能测试

                String s1 = "0123456789";
                String s2 = s1 + s1 + s1;
                String s3 = s1 + s1 + s1 + s1 + s1 + s1;
                long t0 = System.currentTimeMillis();
                for (int i = 0; i < 500000; i++) {

                String s4 = new StringBuilder(s1.length() + s2.length() + s3.length()).append(s1).append(s2).append(s3).toString();

//          String s4 = s1 + s2 + s3;

                }
                System.out.println(System.currentTimeMillis() - t0);

它并不完美,但结果似乎证明我的版本快了约30%。在我的笔记本(Celeron 925)上,它为ver.1 aganist提供~230 ms,为ver.2提供300 ms。实际上这是我的预期。所以我认为如果javac以更有效的方式编译字符串连接将是一个好主意。有足够的行像

return "\\Q" + s + "\\E";

甚至在JDK课程中。最后一行来自java.util.Pattern,它是为效率而设计的

1 个答案:

答案 0 :(得分:4)

取决于您执行它的环境。如果没有某种测试,就不可能肯定地认为一个比另一个好。

那就是说,我同意提前了解最终尺寸可能会带来一些好处。

我怀疑如果你写一个微基准测试,你会发现差异在几乎所有应用中都是微不足道的。

编辑基准建议:

我看到你在帖子中添加了一些实际数据。恭喜!你走在正确的轨道上: - )

不幸的是,Java有许多功能,这些功能对于编写正确的基准测试是不利的。如果您希望结果准确,您应该查看How do I write a correct micro-benchmark in Java?。同样值得考虑的是,在这种情况下看起来很大的加速比在“真实”程序的背景下看起来要小得多。单个数据库提取(以毫秒为单位)可以轻松地使内存分配中的任何增益完全无趣(以纳秒为单位)。