2012-08-28 72 views
3

我与我的朋友就此发生了争执。 考虑以下片断,扩展循环性能

for(i=0; i<someList.size(); i++) { 
    //some logic 
    } 

这里someList.size()将每次迭代被执行,因此建议迁移这个大小计算到外部(前)的循环。

现在,当我使用的扩展对于这样的循环会发生什么,

for(SpecialBean bean: someBean.getSpecialList()) { 
//some logic 
} 

是否需要移动someBean.getSpecialList()到外循环? 如果我保留第二个代码段,someBean.getSpecialList()会执行多少次?

回答

6

第一个示例中的一个更严重的问题是,如果将其应用于LinkedList,将导致O(n )的性能。根据情况的不同,列表大小的计算可能需要O(n),因此O的另一个来源是复杂性,但大小更有可能被缓存。

您的第二个示例编译为通过Iterator进行迭代,并将仅评估someBean.getSpecialList().iterator()一次。

+2

为什么要投票?这是最好的答案 – ant

+0

Downvoter,解释你的downvote! –

+0

您能否澄清LinkedList(如果使用)将如何导致O(n^2)? – Uzair

0

for each变化将是相同的,如下

for (Iterator i = c.iterator(); i.hasNext();) { 
doSomething((Element) i.next()); 
} 

项目46:不想的for-each循环到传统为有效的Java

的环 for-each循环提供了令人信服的优于在清晰度和错误预防方面的循环,没有性能损失。你应该尽可能地使用它。

所以我的第一个猜测是错误的,没有惩罚使用for each循环内的函数。

0

的第一个片段另一种方法是:

for(i=0, l=someList.size(); i<l; i++) { 
    //some logic 
} 

关于for..each循环,以getSpecialList()呼叫将只进行一次(你可以通过添加一些调试/日志验证这一点在该方法内)。

2

从46项有效的Java由约书亚·布洛克:

的for-each循环,在1.5版推出,摆脱杂乱 并通过隐藏迭代器或索引错误的机会完全变量为 。将所得成语同样适用于 集合和数组:

//用于遍历集合和数组为 优选成语(元件E:元件){ doSomething的(E); }当看到冒号(:)时,将其读为“in”。因此,上面的循环读为“对于元素中的每个元素e”。注意 使用for-each循环没有性能损失,甚至数组为 。实际上,在某些情况下,它可能会比普通的for循环提供轻微的性能优势,因为它仅计算一次数组索引的限制 。虽然您可以手动执行此操作(第45项),但程序员并不总是这样做。

is-there-a-performance-difference-between-a-for-loop-and-a-for-each-loop

0

参见作为扩展循环使用来自可迭代截取的迭代器,这将是不可能的或合理的执行多于一次someBean.getSpecialList()更多。将它移到循环之外不会改变循环的性能,但如果它提高了可读性,则可以这样做。

注意:如果按索引迭代,随机访问集合的速度可能会更快。 ArrayList,因为它不创建Iterator,但对于不支持随机访问的索引集合来说速度较慢。