31

ここで、強化された for ループは通常の for ループよりも効率的であると読みました。

http://developer.android.com/guide/practices/performance.html#foreach

それらの効率の違いを検索したところ、見つかったのは次のとおりです。通常の for ループの場合、配列の長さやサイズなどを調べるために追加のステップが必要です。

for(Integer i : list){
   ....
}


int n = list.size();
for(int i=0; i < n; ++i){
  ....
}

しかし、これが唯一の理由でしょうか? 強化された for ループは通常の for ループより優れているのでしょうか? その場合、強化されたfor ループを理解するのが少し複雑になるため、通常の for ループを使用することをお勧めします。

興味深い問題については、これを確認してください: http://www.coderanch.com/t/258147/java-programmer-SCJP/certification/Enhanced-Loop-Vs-Loop

これら 2 種類の for ループの内部実装について説明したり、拡張されたfor ループを使用する他の理由を説明したりできますか?

4

7 に答える 7

58

強化された for ループがより効率的であると言うのは、少し単純化しすぎています。そうかもしれませんが、多くの場合、昔ながらのループとほぼ同じです。

最初に注意すべきことは、コレクションの場合、拡張 for ループは を使用するIteratorため、 を使用してコレクションを手動で反復処理するIteratorと、拡張 for ループとほぼ同じパフォーマンスが得られるはずです。

強化された for ループが単純に実装された従来のループよりも高速な場所の 1 つは、次のようなものです。

LinkedList<Object> list = ...;

// Loop 1:
int size = list.size();
for (int i = 0; i<size; i++) {
   Object o = list.get(i);
   /// do stuff
}

// Loop 2:
for (Object o : list) {
  // do stuff
}

// Loop 3:
Iterator<Object> it = list.iterator();
while (it.hasNext()) {
  Object o = it.next();
  // do stuff
}

この場合、ループ 1 はループ 2 とループ 3 の両方よりも遅くなります。なぜなら、位置 で要素を見つけるために、各反復でリストを (部分的に) トラバースする必要があるためiです。ただし、ループ 2 と 3 は、Iterator. ループ 3 は、ループ 2 でコードを記述したときにコンパイラが生成するものとほぼ同じであるため、ループ 2 と 3 のパフォーマンスもほぼ同じです。

于 2012-07-19T07:00:01.963 に答える
7

強化された for ループは、通常の for ループよりも効率的であると読みました。

実際には、プログラムの効率が悪い場合もありますが、ほとんどの場合、まったく同じです。

開発者にとってより効率的であり、多くの場合、はるかに重要です

for-each ループは、コレクションを反復処理する場合に特に役立ちます。

List<String> list = 
for(Iterator<String> iter = list.iterator(); list.hasNext(); ) {
    String s = list.next();

のように書く方が簡単です (しかし、同じことを行うため、プログラムにとっては効率的ではありません)。

List<String> list = 
for(String s: list) {

インデックスによってランダムにアクセス可能なコレクションにアクセスする場合、「古い」ループを使用する方がわずかに効率的です。

List<String> list = new ArrayList<String>(); // implements RandomAccess
for(int i=0, len = list.size(); i < len; i++) // doesn't use an Iterator!

コレクションで for-each ループを使用すると、常に Iterator が使用されますが、これはランダム アクセス リストの効率がわずかに低下します。

私の知る限り、 for-each ループを使用することはプログラムにとって決して効率的ではありませんが、私が言ったように、開発者の効率はしばしばはるかに重要です.

于 2012-07-19T06:58:04.623 に答える
3

foreach ループは、次の種類のループと同じくらい効率的です。

for (Iterator<Foo> it = list.iterator(); it.hasNext(); ) {
     Foo foo = it.next();
     ...
}

厳密に同等だからです。

を使用してリストを反復処理する場合

int size = list.size();
for (int i = 0; i < size; i++) {
    Foo foo = list.get(i);
    ...
}

次に、 foreach ループはループと同等のパフォーマンスを発揮しますが、 ArrayList に対してのみです。LinkedList の場合、繰り返しのたびにith 要素に到達するまでリストのすべてのノードをトラバースする必要があるため、ループのパフォーマンスは最悪になります。

foreach ループ (または同じ反復子に基づくループ) には、反復子が現在のノードへの参照を保持し、反復ごとに単純に次のノードに移動するため、この問題はありません。すべてのタイプのリストでうまく機能するため、これは最良の選択です。また、意図をより明確に表現し、ループ内でインデックスをインクリメントしたり、ネストされたループの場合に間違ったインデックスを使用したりするリスクがないため、より安全です。

于 2012-07-19T07:02:36.677 に答える
3

for-each は Iterator インターフェイスを使用します。「古い」スタイルよりも効率的であるとは思えません。Iterator は、リストのサイズもチェックする必要があります。

主に読みやすさのためです。

LinkedList のような非ランダム アクセス コレクションの場合は高速になるはずですが、比較は不公平です。とにかく、2 番目の実装 (インデックス アクセスが遅い) には慣れていないでしょう。

于 2012-07-19T06:59:42.297 に答える
0

効果的な Java から:

配列をループするための標準的なイディオムは、必ずしも冗長なチェックをもたらすとは限りません。最新の JVM 実装では、それらを最適化して排除しています。

しかし Josh Bloch は、JVM がそれらをどのように最適化するかについて説明していません。

于 2012-07-19T09:50:01.217 に答える