web-dev-qa-db-ja.com

Javaループ効率( "for" vs. "foreach")

(JVMのコンパイルと最適化のコツをよく知っている人への質問... :-)

他のパターンより明らかに優れている「for」および「foreach」パターンはありますか?

次の2つの例を検討してください。

public void forLoop(String[] text)
{
    if (text != null)
    {
        for (int i=0; i<text.length; i++)
        {
            // Do something with text[i]
        }
    }
}

public void foreachLoop(String[] text)
{
    if (text != null)
    {
        for (String s : text)
        {
            // Do something with s, exactly as with text[i]
        }
    }
}

forLoopforeachLoopより速いですか、遅いですか?

どちらの場合でも、text配列は健全性チェックを必要としなかったと仮定すると、明確な勝者がいるのか、それとも電話をかけるには近すぎますか?

編集:回答の一部で述べたように、パフォーマンスは配列に対して同じである必要がありますが、「foreach」パターンはリストのような抽象データ型に対してわずかに優れている可能性があります。 this answer も参照してください。これは主題について説明しています。

27
PNS

JLSのセクション14.14.2 から:

それ以外の場合、Expressionには必ず配列型T []が含まれます。 L1 ... Lmを、拡張forステートメントの直前の(おそらく空の)ラベルのシーケンスとします。次に、拡張forステートメントの意味は、次の基本forステートメントによって与えられます。

T[] a = Expression;
L1: L2: ... Lm:
for (int i = 0; i < a.length; i++) {
        VariableModifiersopt Type Identifier = a[i];
        Statement
}

言い換えれば、同じコードにコンパイルされることになります。

明確な勝者は間違いなくあります。拡張forループは読みやすいです。それはあなたの第一の関心事であるべきです-あなたが最も読みやすいフォームがあなたの望むほどうまく機能しないことを証明したときだけ、あなたはconsiderこの種のことを微最適化するべきです。

61
Jon Skeet

実行時間を測定する独自の簡単なテストを作成できます。

long start = System.currentTimeMillis();
forLoop(text);
long end = System.currentTimeMillis();
long result = end - start;

結果は実行時間です。

4
alnasfire

array型を使用しているため、パフォーマンスの違いは問題になりません。 optimizationファネルを通過した後、同じパフォーマンスを提供することになります。

しかし、ListのようなADTを使用している場合、forEachLoopが複数のget(i)呼び出しと比較して明らかに最適な選択です。

3
Navneeth G

パフォーマンスの問題があることがわかっている場合を除き、ほとんど毎回読みやすいオプションを選択する必要があります。

この場合、それらは同じであることが保証されています。

唯一の違いは、text.lengthこれは、高速ではなく、低速になる可能性があります。

また、テキストが静的にnullにならないようにします。例えば@NotNullアノテーションを使用します。コンパイル/ビルド時にこれらの問題をキャッチする方が適切です(より高速になります)

3
Peter Lawrey

For-eachループを使用しても、配列であってもパフォーマンスが低下することはありません。実際、状況によっては、配列インデックスの制限を一度しか計算しないため、通常のforループよりもわずかにパフォーマンスが向上する場合があります。詳細については、この post に従ってください。

2
Kuldeep Jain