for ループまたは while ループで反復しますか?
質問
次のようなコードをよく見かけます。
Iterator i = list.iterator();
while(i.hasNext()) {
...
}
しかし、私はそれを(Java 1.5が利用できない場合、またはJava 1.5が使用できない場合)次のように書きます。
for(Iterator i = list.iterator(); i.hasNext(); ) {
...
}
なぜなら
- 短いです
- を維持する
i
より小さな範囲で - 混乱の可能性が減ります。(は
i
その間外で使用しますか?どこですかi
宣言した?)
複雑な処理を実行するために複雑なコードを作成するだけで済むように、コードはできるだけ簡単に理解できるべきだと考えています。どう思いますか?どちらが良いでしょうか?
解決
私は for ループの方が好きです。なぜなら、反復子のスコープも for ループだけに設定するからです。
他のヒント
while、for、foreach 構造には適切な使用法があります。
while
- 反復処理を行っており、ループするかどうかの決定要因が単に条件に基づいている場合にこれを使用します。このループ構造では、インデックスの保持は二次的な関心事にすぎません。すべては条件に基づいている必要がありますfor
- ループしていて、主な関心事が配列/コレクション/リストのインデックスである場合は、これを使用します。を通過する可能性が最も高い場合は、 for を使用する方が便利です。 全て いずれにせよ、要素を特定の順序で (たとえば、ソートされたリストを逆方向に進むなど)。foreach
- 順序に関係なく、単にコレクションを確認する必要がある場合にこれを使用します。
もちろん上記には例外もありますが、どれを使用するかを決定するときに私が使用する一般的なルールです。そうは言っても私がよく使うのは foreach
もっと頻繁に。
なぜ for-each 構造を使用しないのでしょうか?(私はしばらく Java を使用していませんでしたが、これは C# に存在し、Java 1.5 にもこれがあると確信しています):
List<String> names = new ArrayList<String>();
names.add("a");
names.add("b");
names.add("c");
for (String name : names)
System.out.println(name.charAt(0));
ご指摘のように、範囲が最大の問題だと思います。
「while」の例では、イテレータはループの外で宣言されているため、ループが終了した後もイテレータは存在し続けます。これにより、この同じイテレータが後で再び使用された場合に問題が発生する可能性があります。E.g.別のループで使用する前に初期化を忘れる可能性があります。
「for」の例では、反復子はループ内で宣言されるため、その範囲はループ内に制限されます。ループの後に使用しようとすると、コンパイラ エラーが発生します。
イテレータを 1 回だけ使用して破棄する場合は、2 番目の形式が推奨されます。それ以外の場合は、最初の形式を使用する必要があります
私見ですが、 のために このコードを英語の観点から見ると、このシナリオではループが読みにくくなります。作成者が不正行為を行うコードに取り組んでいます のために ループします、そしてそれはきれいではありません。以下を比較してください。
for (; (currUserObjectIndex < _domainObjectReferences.Length) && (_domainObjectReferences[currUserObjectIndex].VisualIndex == index); ++currUserObjectIndex)
++currNumUserObjects;
対
while (currUserObjectIndex < _domainObjectReferences.Length && _domainObjectReferences[currUserObjectIndex].VisualIndex == index)
{
++currNumUserObjects;
++currUserObjectIndex;
}
反復処理を行う場合、「for」ループの方が明確で適切であることに私も同意します。
「while」ループは、ポーリング、または終了条件を満たすループの数がループ内のアクティビティに基づいて変化する場合に適しています。
この場合はおそらく重要ではありませんが、コンパイラ、VM、CPU は通常、ループのパフォーマンス (および近い将来の並列) を向上させる特別な最適化テクニックを内部で使用します。 while ループ (実際にどのように実行されるかを判断するのが難しいため)。しかし、ほとんどの場合、コードの明瞭さは最適化よりも優先されます。
for ループを使用すると、現在動作している for ループのみの変数のスコープが設定されるため、単一の変数を操作できます。ただし、while ループではこれは不可能です。例えば:
int i;for(i=0;in1;i++) 何かをしてください。
for(i=0;i n2;i+=2) 何かをします。
したがって、最初のループの後、最後に i=n1-1 になります。ただし、2 番目のループを使用しているときに、i を再び 0 に設定できます。 しかし
int i=0;
while(i が制限未満) { 何かをする ..;i++;}
したがって、 i は最後にlimit-1に設定されます。したがって、別の while ループで同じ i を使用することはできません。
どちらでも構いません。私自身 for () を使用していますが、コンパイルに問題があるかどうかはわかりません。両方ともほぼ同じものまで最適化されているのではないかと思います。
可能な限り for ループを使用するべきであるという意見には同意しますが、場合によっては、ループ本体の反復子を制御するより複雑なロジックが存在することがあります。その場合は while を使用する必要があります。
わかりやすくするために、私は for ループでした。を使用している間、 while ループ 何らかの不確定な状況に直面したとき。
どちらも問題ありませんが、場合によっては Iterator に直接アクセスすると便利なことがあることに注意してください (特定の条件に一致する要素を削除する場合など、for(To : 内で collection.remove(o) を実行すると ConcurrentModificationException が発生します)。コレクション) ループ)。
私は for(blah :ああ) [foreach] 構文は、私にとってはより自然に読みやすいと思われるため、ほとんどの場合使用されます。一般にイテレータの概念は、プログラミング以外では実際には類似点がありません。
学術界では、プログラムに関する推論が複雑でなくなるため、while ループを好む傾向があります。コードが読みやすくなるため、私は for ループまたは foreach ループ構造を好む傾向があります。
どちらも実際には問題ありませんが、読みやすいため、私は最初の例を使用することが多いです。
while() ループを使用すると、各行で発生する操作が少なくなり、コードを初めて使用する人でも何が起こっているのかを理解しやすくなります。
このタイプの構造を使用すると、初期化を共通の場所 (メソッドの先頭) にグループ化することもできるため、コメントの作成や、初めて読む人の概念化も簡素化されます。