9

我想向更有经验的开发人员询问一件简单但对我来说并不明显的事情。假设您有这样的代码(Java):

for(int i=0; i<vector.size(); i++){
   //make some stuff here
}

我经常遇到这样的说法,所以也许它没有错。但对我来说,似乎没有必要在每次迭代中调用 size 方法。我会使用这样的方法:

int vectorSize = vector.size();
for(int i=0; i<vectorSize; i++){
    //make some stuff here
}

这里也是一样的:

for(int i=0; i<myTreeNode.getChildren().size(); i++){
   //make some stuff here
}

我绝对不是编程方面的专家,所以我的问题是:我是在寻找一个完整的对冲还是在专业代码中处理这些细节很重要?

4

3 回答 3

8

A method invocation requires that the JVM does indeed do additional stuff. So what you're doing, at first view seems like an optimization.

However, some JVM implementations are smart enough to inline method calls, and for those, the difference will be nonexistent.

The Android programming guidelines for example always recommend doing what you've pointed out, but again, the JVM implementation manual (if you can get your hands on one) will tell you if it optimizes code for you or not.

于 2013-04-25T19:02:51.053 回答
2

通常size()是一个小的恒定时间操作,因此调用size的成本与执行循环体的成本相比是微不足道的,及时编译器可能会为您处理这种优化;因此,这种优化可能没有太多好处。

也就是说,这种优化不会对代码的可读性产生不利影响,因此不是可以避免的;由于这个原因,通常应该避免只影响速度的代码优化(与例如将 O(n) 操作更改为 O(1) 操作的优化相反),例如,您可以展开循环

int i;
int vectorSizeDivisibleBy4 = vectorSize - vectorSize % 4; // returns lowest multiple of four in vectorSize
for(i = 0; i < vectorSizeDivisibleBy4; i += 4) {
    // loop body executed on [i]
    // second copy of loop body executed on [i+1]
    // third copy of loop body executed on [i+2]
    // fourth copy of loop body executed on [i+3]
}
for(; i < vectorSize; i++) { // in case vectorSize wasn't a factor of four
    // loop body
}

通过将循环展开四次,您将i < vectorSize评估的次数减少了四倍,代价是使您的代码变得难以阅读(它也可能会弄乱指令缓存,从而导致负面的性能影响)。不要这样做。但是,就像我说的,int vectorSize = vector.size()不属于这一类,所以就这样吧。

于 2013-04-25T19:07:29.540 回答
0

乍一看,您建议的替代方案接缝优化,但就速度而言,它常用方法相同,因为:

在 java 向量中调用 size() 函数的复杂度时间具有 O(1) 阶复杂度,因为每个向量始终存储一个包含其大小的变量,因此您无需在每次迭代中计算其大小,你只需访问它。

注意:您可以在http://www.docjar.com/html/api/java/util/Vector.java.html中看到 size() 函数只是返回一个受保护的变量 elementCount。

于 2013-04-25T19:16:15.450 回答