2012-05-11 13 views
3

可能性の重複:ベストプラクティス

List e = {element1, element2, ...., elementn}; 
for(int i = 0; i < e.size(); i++){//Do something in here 
}; 

と別のブロック:私は、コードのブロックを持ってJavaで
for loop optimization

List e = {element1, element2, ...., elementn}; 
int listSize = e.size(); 
for(int i = 0; i < listSize; i++){//Do something in here 
}; 

私は、最初のブロックでi++ならば、e.size()をもう一度計算して、forのループの条件を比較する必要があるので、2番目のブロックが優れていると思います。それは間違っていますか? 上記の2つのブロックを比較すると、書き込み用のベストプラクティスは何ですか?そしてなぜ?明確に説明してこのループを自分で試してみてください

+1

2回目は、繰り返しごとにリストサイズを計算しないためです。 –

答えて

14

は個人的に私が代わりに文の強化に使用したい:

for (Object element : e) { 
    // Use element 
} 

あなたがない限り必要もちろんのインデックス、。

の2つの形式のうちの1つを使用していた場合、最初のものを使用します(そのループでのみ使用される別のローカル変数を紹介しません)。それは問題を引き起こしていた。 (ほとんどのリストの実装では、e.size()はJITによってインライン化できる単純な可変アクセスです)

+0

+1のインライン展開....... –

+0

[http://developer.android.com/guide/practices/design/performance.html](http://developer.android.com/guide/practices/ design/performance.html)前のリンクを読んでいるので、2番目のブロックは最初のブロックよりも優れています! : –

+2

@キングフィッシャー:これはJITがより原始的だったAndroid用の*具体的なものですが、とにかくこの状況に対処しているとは驚くことはありません。証拠*。 –

-1

2番目の方が良いですよ、体のファーループではおそらくuはこの文を実行します e.remove、次にeのサイズが変更され、だから、ループの前にパラメータのサイズを保存する方が良いです

+0

それはConcurrentModificationException(またはそのようなもの)をスローしませんか? – jahroy

+0

いいえ、loog内のリストの要素を削除すると例外はスローされません。スキャンせずに要素を取得します。 –

+0

リストから項目を削除すると、サイズが実際に変更されるため、ループ境界その後壊れてしまいます。私の最初のフォームの引数のように聞こえます(要素をスキップしないように 'i 'を減らす必要もあります)。 –

0

私はそれほど確かではありませんが、私はjavaのオプティマイザが静的な値で値を置き換えると思うので、最終的には同じになります。

0

第1ブロックでは、e.size()と呼ぶのは、JVMに余分な負担となるループ内での操作であるためです。

+1

ベストプラクティスでは、マイクロ最適化ではなく、最も可読性の高いコードを書くことを提案しています。 –

+0

ありがとう@JonSkeet。しかし、多くの場所で誤読や誤解されることがよくあります。また、ベストプラクティスとは、JVMが実行するにはあまりにも軽いコードを書くことを意味します。 – UVM

6

通常、最も簡単で可読性の高いコードが最良の選択であり、すべてが同等です。 Javaの場合、強化されたforループ(Iterableを実装するすべてのクラスで動作します)が移動する方法です。

for (Object object : someCollection) { // do something } 

あなたが投稿した2人の意見だけで、私は最初の方が良い選択肢だと思います。より読みやすく、あなたが書いたように、JITはあなたが書いた大量のコードを最適化しようとします。

EDIT:「時期尚早最適化はすべての悪の根源」という言葉を聞いたことがありますか? 2番目のブロックは早すぎる最適化の例です。

+0

Jon Skeetが示唆しているように、何らかの理由で反復処理中のコレクションにインデックスが必要な場合は、ループの最初の形式を使用してください。 – Jon

+1

+1達成可能で包括的な – GingerHead

+1

[_リンクHere_](http://developer.android.com/guide/practices/design/performance.html)ここのリンクを読むと、2番目のブロックは最初のブロックよりも優れています。 –

1

はい、size()メソッドの呼び出しを繰り返し実行しない限り、2番目のフォームはわずかに効率的です。コンパイラはこの種の最適化を自分たちでやっています。

しかし、これがアプリケーションのパフォーマンスのボトルネックになる可能性は低いです。 Avoid premature optimisation。あなたのコードをきれいで読みやすいものにしましょう。

2

(あなたはインデックス変数が必要な場合)私はいつも使用します。

List e = {element1, element2, ...., elementn}; 
for(int i = 0, size = e.size(); i < size; i++){ 
    // Do something in here 
}; 

e.size()は高価な操作になる可能性があるため。

あなたの2番目のオプションは、forループの外側に新しい変数を導入するため、良くありません。変数の可視性を可能な限り制限しておくことをお勧めします。

そうでない場合

for (MyClass myObj : list) { 
    // Do something here 
} 

でもきれいですが、(インデックスアプローチはIteratorをインスタンス化する必要はありません)、小さなパフォーマンスヒットを導入することがあります。

+0

+1 forループのサイズ変数を初期化すると、非常にエレガントだと思う(本当に必要ない限り、私はマイクロ最適化を信じていないが)。とにかく、良いスニペット:) – szegedi

+0

-1 e.size()それは高価な操作ではない、それはなぜだろう! e.size()メソッドの実装を逆コンパイルすると、戻り値の大きさが変わってしまいます。これは "高価な"操作ではありません。 –

+0

@AndreaBoriこれは単なる例です。もちろん、シンプルな 'List'では高価な操作ではありません。しかし、forループの条件部分でメソッド呼び出しを使用しないことがベストプラクティスです。 –

1

HotSpotはほとんどの場合サイクルからe.size()を移動します。それでListのサイズは一度だけ計算されます。 はこのから脱出することができますint型の変数ごとに初期化することができる..私は、これははるかに良いはずだと思う

for (Object elem: e) { 
    //Do something 
} 
1

..

List e = {element1, element2, ...., elementn}; 
int listSize = e.size(); 
int i=0; 
for(i = 0; i < listSize; i++){//Do something in here 
}; 

は私のためとして、私は以下の表記を好みます

4

LinkedListクラスのsize()実装をチェックすると、要素がリストに追加または削除されたときにサイズがインセントまたはデクリメントされます。 size()を呼び出すと、このプロパティの値が返され、計算は含まれません。
size()メソッドを直接呼び出すと、別の整数のために保存するときと同じように改善されるはずです。

+1

+1素敵な態度 – GingerHead

0

この番号付けとイテレータとチェックを避けるには、パフォーマンスを最大限に引き出す次の単純でわかりやすいコードを使用します。
第二は、それだけで計算しているため、あなたが言ったように優れている:
は、上記の二つの形式のどちらかを選択するには、次のインデックスは、その後、必要な場合は、これが最大の性能を持っているのはなぜ は

for (Object object : aCollection) { 
// Do something here 
} 

(詳細は予定されています)サイズは一度。

0

私は今、短い理解可能なコードを書く傾向があると思うので、最初の選択肢はより良いです。