在Java中优化for循环有用吗?

3

可能重复:
for loop optimization

假设我们想循环遍历字符串s中的字符。我认为以下代码是默认的。

for( int i = 0; i < s.length(); i++ ) {
    doSomethingWith( s.charAt( i ) );
}

问题1:为什么我经常看到以下内容?

final int length = s.length();
for( int i = 0; i < length; i++ ) {
    doSomethingWith( s.charAt( i ) );
}

乍一看,这似乎是合理的,因为不等式在每次迭代中都会被评估。然而,我认为VM应该会对此进行优化,因为字符串是不可变的。您有什么想法?如果我们遍历一个可变结构(没有被任何其他线程引用),会发生什么?如果length()不能保证以O(1)运行呢?
问题#2:有些人似乎认为将++i替换为i++可以加快代码速度。他们是对的吗?同样,这不是我所期望的,但我并不确定。
我们都知道不要过早优化。同时,如果我们可以在几乎没有任何代价的情况下产生稍微快一点的代码,那么我们就不应该愚蠢地放弃。当然,有人可能会说这两个“优化”都会影响可读性,但我认为这种损害非常小,在某些情况下是合理的。
我试图测量任何性能差异,但很难得出确切的结果。虽然这应该解决任何特定应用程序的问题,但我在这里的目标是洞察力和一个普遍的答案。
(尽管我写这篇文章时考虑了HotSpot VM,但也可以考虑其他平台,比如移动设备。)
2个回答

5

问题1:为什么我经常会看到以下情况?

第一个例子是过早优化。人们这样做的原因是他们通常不会分析代码以查看瓶颈在哪里,而只是试图猜测。

如果length()不能保证以O(1)运行,那该怎么办?

那么进行此优化将更有意义。如果您知道计算长度是一项昂贵的操作并且该值不会改变,则计算一次并存储结果可能会提高性能。

问题2:有些人似乎认为用++i替换i++可以加快代码速度。他们对吗?虽然这不是我预期的结果,但我并不确定。

他们是错误的。他们的论点是i++必须创建变量的临时副本,而++i则不必。这在很长时间以前的C或C++中曾经是正确的,当时编译器不擅长优化。但是,在Java中这不是真的。


3

乍一看这似乎很合理,因为不等式在每次迭代中都会被评估。然而,我会期望虚拟机会进行优化,因为字符串是不可变的。

编译器会进行优化。像 i < s.length(); 这样做是可以的。

有些人似乎认为将 ++i 替换为 i++ 可以加速代码执行。

除非你将 ++i 的返回值赋给某个变量,否则它不会加速代码执行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接