增强了循环性能

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()如果我要保留第二个片段,它会执行多少次?

Mar*_*nik 8

重复呼叫list.size()不会导致任何性能损失.JIT编译器最有可能内联它,即使它没有,它仍然会相当便宜,因为它只涉及读取字段的值.

你的第一个例子的一个更严重的问题是,循环体将不得不涉及list.get(i)并且为了获得LinkedList第i个元素具有O(i)成本,由于指针追逐具有非常显着的常数因子,这转化为数据依赖性加载CPU级别.CPU的预取器无法优化此访问模式.

这意味着当应用于a时,整体计算复杂度将为O(n 2)LinkedList.

您的第二个示例将编译为迭代通过Iterator,并将someBean.getSpecialList().iterator()仅评估一次.iterator.next()在所有情况下,成本是恒定的.


avi*_*iad 5

来自 Joshua Bloch 所著的《Effective Java》第 46 条:

\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
\n\n

另请参见for-loop 和 for-each-loop 之间是否存在性能差异

\n