(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]
}
}
}
forLoop
はforeachLoop
より速いですか、遅いですか?
どちらの場合でも、text
配列は健全性チェックを必要としなかったと仮定すると、明確な勝者がいるのか、それとも電話をかけるには近すぎますか?
編集:回答の一部で述べたように、パフォーマンスは配列に対して同じである必要がありますが、「foreach」パターンはリストのような抽象データ型に対してわずかに優れている可能性があります。 this answer も参照してください。これは主題について説明しています。
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この種のことを微最適化するべきです。
実行時間を測定する独自の簡単なテストを作成できます。
long start = System.currentTimeMillis();
forLoop(text);
long end = System.currentTimeMillis();
long result = end - start;
結果は実行時間です。
array
型を使用しているため、パフォーマンスの違いは問題になりません。 optimization
ファネルを通過した後、同じパフォーマンスを提供することになります。
しかし、ListのようなADTを使用している場合、forEachLoop
が複数のget(i)
呼び出しと比較して明らかに最適な選択です。
パフォーマンスの問題があることがわかっている場合を除き、ほとんど毎回読みやすいオプションを選択する必要があります。
この場合、それらは同じであることが保証されています。
唯一の違いは、text.length
これは、高速ではなく、低速になる可能性があります。
また、テキストが静的にnullにならないようにします。例えば@NotNullアノテーションを使用します。コンパイル/ビルド時にこれらの問題をキャッチする方が適切です(より高速になります)
For-eachループを使用しても、配列であってもパフォーマンスが低下することはありません。実際、状況によっては、配列インデックスの制限を一度しか計算しないため、通常のforループよりもわずかにパフォーマンスが向上する場合があります。詳細については、この post に従ってください。