Uza*_*air 5 java performance for-loop
我和我的朋友就此发生了争执.考虑下面的片段,
for(i=0; i<someList.size(); i++) {
//some logic
}
Run Code Online (Sandbox Code Playgroud)
这someList.size()将在每次迭代时执行,因此建议将此大小计算迁移到循环外部(之前).
现在当我像这样使用扩展for循环时会发生什么,
for(SpecialBean bean: someBean.getSpecialList()) {
//some logic
}
Run Code Online (Sandbox Code Playgroud)
是否有必要转移someBean.getSpecialList()到循环外?someBean.getSpecialList()如果我要保留第二个片段,它会执行多少次?
重复呼叫list.size()不会导致任何性能损失.JIT编译器最有可能内联它,即使它没有,它仍然会相当便宜,因为它只涉及读取字段的值.
你的第一个例子的一个更严重的问题是,循环体将不得不涉及list.get(i)并且为了获得LinkedList第i个元素具有O(i)成本,由于指针追逐具有非常显着的常数因子,这转化为数据依赖性加载CPU级别.CPU的预取器无法优化此访问模式.
这意味着当应用于a时,整体计算复杂度将为O(n 2)LinkedList.
您的第二个示例将编译为迭代通过Iterator,并将someBean.getSpecialList().iterator()仅评估一次.iterator.next()在所有情况下,成本是恒定的.
来自 Joshua Bloch 所著的《Effective Java》第 46 条:
\n\n\n\n\n版本 1.5 中引入的 for-each 循环通过完全隐藏迭代器或索引变量来消除混乱和出错的机会。由此产生的习惯用法同样适用于集合和数组:
\n\n// 迭代集合和数组的首选习惯用法 for\n (Element e : elements) {\n doSomething(e); 当你看到冒号 (:) 时,将其读作 \xe2\x80\x9cin.\xe2\x80\x9d 因此,对于 elements.\xe2\x80\ 中的每个元素 e,上面的循环读作 \xe2\x80\x9c x9d 请注意,使用 for-each 循环不会带来性能损失,即使对于数组也是如此。事实上,在某些情况下,它可能比普通的 for 循环具有轻微的性能优势,因为它只计算一次数组索引的限制。虽然您可以手动执行此操作(第 45 项),但程序员并不总是这样做。
\n
另请参见for-loop 和 for-each-loop 之间是否存在性能差异
\n