我只是好奇:这两个循环实现之间的速度和性能是否存在差异?假设 size()方法返回处理一组元素的数组,集合或对象的长度(实际上它来自 XOM api)。
实施1:
int size = someArray.size();
for (int i = 0; i < size; i++) {
// do stuff here
}
实施2:
for (int i = 0; i < someArray.size(); i++) {
// do stuff here
}
答案 0 :(得分:3)
从性能的角度来看,差别不大。这是因为可以优化循环,以便内联size()查找,从而导致性能差异很小。
主要区别在于循环时大小是否发生变化。第一种情况将尝试迭代固定次数。在第二种情况下,迭代次数取决于最终大小()。
答案 1 :(得分:1)
第一个代码段必须执行得更快,因为它只调用size()
一次。第二个片段呼叫size()
N次。取决于impl。它可能会造成重大的惩罚,尤其是如果编译器发现难以内联该方法和/或size()
方法不仅仅返回非易失性变量等。
我已经像for(int i=0, s=someCollection.size(); i<s; i++)
注意:数组没有size()
方法。
答案 2 :(得分:1)
是的,有区别。在第一个循环中,size()方法只调用一次。在第二个中,它在每次迭代时调用。
如果迭代修改了集合的大小(这是非常罕见的),则需要第二个。在大多数情况下,您应该更喜欢第一个,但是限制size变量的范围:
for (int i = 0, size = someArray.size(); i < size; i++) {
// ...
}
但是大多数时候,你应该更喜欢foreach语法:
for (Foo foo : collection) {
// ...
}
将有效地迭代数组或集合,即使对于LinkedList,例如,索引访问不是最佳的。
答案 3 :(得分:1)
不要担心,最近JVM优化非常激进。
使用第二种形式,因为它更具可读性,而且最有可能。过早优化yada yada。
当你确实需要提高速度时,请先进行剖析,不要猜测。
在本地变量中缓存size()极不可能显着地使您的应用受益。如果是这样,您必须对庞大的数据集进行简单的操作。在这种情况下,你根本不应该使用ArrayList。
答案 4 :(得分:0)
也许值得注意的是这个结构:
for (String s : getStringsList()) {
//...
}
仅调用getStringsList()
一次,然后在后台操作迭代器。因此,在getStringsList()
内执行冗长的操作或更改某些状态是安全的。
答案 5 :(得分:0)
始终避免在循环之外可以执行的任何操作,如方法调用,为变量赋值或测试条件。
方法调用比没有调用的等效代码更昂贵,并且通过一次又一次地重复方法调用,您只需为应用程序增加开销。
将所有方法调用移出循环,即使这需要重写代码。
好处: -
除非编译器对其进行优化,否则将为循环中的每次迭代计算循环条件。
如果条件值不会改变,如果将方法调用移出循环,代码将执行得更快。
注意: -
如果方法返回一个在循环期间不会改变的值,则在循环之前将其值存储在临时变量中。
因此,它的值存储在循环外部的临时变量大小中,然后用作循环终止条件。