5

私はこれに関して私の友人と議論をしました。以下のスニペットを検討してください。

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

ここでsomeList.size()は反復ごとに実行されるため、このサイズ計算をループの外側(前)に移行することをお勧めします。

このように拡張forループを使用するとどうなりますか?

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

someBean.getSpecialList()ループの外側に移動する必要がありますか?someBean.getSpecialList()2番目のスニペットをそのまま保持した場合、何回実行されますか?

4

5 に答える 5

8

を繰り返し呼び出すとlist.size()、パフォーマンスが低下することはありません。JITコンパイラーはおそらくインライン化するでしょうし、インライン化しない場合でも、フィールドの値を読み取るだけなので、かなり安価です。

最初の例でのはるかに深刻な問題は、ループ本体が関与する必要があることです。また、ilist.get(i)番目の要素にアクセスすると、ポインター追跡のために非常に重要な一定の係数を持つO(i )コストが発生します。これは、データに依存します。 CPUレベルでロードします。CPUのプリフェッチャーは、このアクセスパターンを最適化できません。LinkedList

これは、に適用すると、全体的な計算の複雑さがO(n 2)になることを意味しLinkedListます。

2番目の例は、を介して反復にコンパイルされ、1回だけIterator評価されsomeBean.getSpecialList().iterator()ます。のコストはiterator.next()すべての場合で一定です。

于 2012-08-28T09:11:42.003 に答える
4

JoshuaBlochによるEffectiveJavaのアイテム46から:

リリース1.5で導入されたfor-eachループは、イテレータまたはインデックス変数を完全に非表示にすることで、混乱とエラーの可能性を取り除きます。結果として得られるイディオムは、コレクションと配列に等しく適用されます。

//(Element e:elements){doSomething(e);のコレクションと配列を反復処理するための推奨イディオム コロン(:)が表示されたら、「in」と読みます。したがって、上記のループは「要素内の各要素eに対して」と解釈されます。配列の場合でも、for-eachループを使用してもパフォーマンスが低下しないことに注意してください。実際、配列インデックスの制限を1回だけ計算するため、状況によっては通常のforループよりもパフォーマンスがわずかに向上する場合があります。これは手動で行うことができますが(項目45)、プログラマーは常にそうするとは限りません。

is-there-a-performance-difference-between-a-for-loop-and-a-for-each-loopも参照してください。

于 2012-08-28T09:10:12.077 に答える
0

for eachバリエーションは以下と同じになります

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

項目46から:for-eachループをEffectivejavaの従来のforループよりも優先

for-eachループは、パフォーマンスを低下させることなく、従来のforループよりも明確でバグ防止の点で魅力的な利点を提供します。できる限り使用する必要があります。

したがって、私の最初の推測は間違っていましたfor each。ループ内の関数を使用してもペナルティはありません。

于 2012-08-28T09:07:37.223 に答える
0

最初のスニペットの代わりは次のようになります。

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

for..eachループに関しては、への呼び出しgetSpecialList()は1回だけ行われます(メソッド内にデバッグ/ロギングを追加することでこれを確認できます)。

于 2012-08-28T09:09:59.713 に答える
0

拡張ループはIterableから取得したIteratorを使用するため、someBean.getSpecialList()複数回実行することは不可能または賢明ではありません。ループの外に移動してもループのパフォーマンスは変わりませんが、読みやすさが向上する場合は変更できます。

注:インデックスで反復する場合、ランダムアクセスコレクションでは高速になる可能性があります(例:ArrayListはイテレーターを作成しないため)が、ランダムアクセスをサポートしないインデックス付きコレクションでは低速になります。

于 2012-08-28T09:11:34.010 に答える