web-dev-qa-db-ja.com

複数のforeachループを解除するにはどうすればよいですか?

コレクションを反復処理し、条件に基づいて何かを行う4つのforeachループがあります。

これが私が今書いているコードです:

boolean breakFlag = false;
String valueFromObj2 = null;
String valueFromObj4 = null;
for(Object1 object1: objects){
  for(Object2 object2: object1){
    // I get some value from object2
    valueFromObj2 = object2.getSomeValue();
    for(Object3 object3 : object2){
      for(Object4 object4: object3){
       // Finally I get some value from Object4.
       valueFromObj4 = object4.getSomeValue();
       // Compare with valueFromObj2 to decide either to break all the foreach loop
       breakFlag = compareTwoVariable(valueFromObj2, valueFromObj4 );
       if(breakFlag){break;}
      } // fourth loop ends here
      if(breakFlag){break;}
    } // third loop ends here
    if(breakFlag){break;}
  } // second loop ends here
  if(breakFlag){break;}
} // first loop ends here

メインオブジェクト(コード内のオブジェクト)はサードパーティプロバイダーのSDKから取得されているため、その部分は変更できません。 Stack Overflowコミュニティに、4つのforeachループすべてを打破するためのより良いアプローチがあるかどうか尋ねたいと思います。または、このコードをリファクタリングして読みやすく、保守しやすい方法が他にある場合。

32
royalghost

最も外側のループでラベルを使用し、すべてのループからジャンプする場合は、このラベルをbreakステートメントに含めます。以下の例では、ラベルOUTERMOSTを使用するようにコードを変更しています。

String valueFromObj2 = null;
String valueFromObj4 = null;
OUTERMOST: for(Object1 object1: objects){
  for(Object2 object2: object1){
    //I get some value from object2
    valueFromObj2 = object2.getSomeValue();
    for(Object3 object3 : object2){
      for(Object4 object4: object3){
        //Finally I get some value from Object4.
        valueFromObj4 = object4.getSomeValue();
        //Compare with valueFromObj2 to decide either to break all the foreach loop
        if( compareTwoVariable(valueFromObj2, valueFromObj4 )) {
          break OUTERMOST;
        }
      }//fourth loop ends here
    }//third loop ends here
  }//second loop ends here
}//first loop ends here
80
Luke Woodward

すべてのループを関数に抽出し、returnを使用します。

20
Alex Reitbort

ラベル付きのbreakステートメントを使用できます。この種類のブレークは、外側のステートメントを終了します

を参照してください。breakステートメント

6
Pierre

ラベルを使用する最も簡単な方法については、 分岐ステートメントJavaチュートリアル を参照してください。forループの一部またはすべてにラベルを付けてから、breakを使用できます。またはcontinueこれらのラベルと組み合わせて。

ラベルを使用する代わりに、代わりにreturnを使用することもできます。コードをメソッド呼び出しにリファクタリングするだけで、ラベルをまったく使用する必要がなくなります。

2
Bill the Lizard

あなたの例はかなり一般的なものなので、何が起こっているのかを言うのは難しいですが、私はあなたが提供したコードからそのような強いコードの匂いを感じています。実際のデータ構造をより意味のあるものにリファクタリングする。

objectsとはどのようなリストですか?他にどのような(おそらく重要)データが含まれていますか?面倒ではない場合は、関連するコードを提供していただければ幸いです。私のリファクタラーはループの山を見るだけですべてのめまいを起こしているからです。

2
Esko

複数のステートメント(実際にはスタックフレーム)を分割または折りたたむ1つの方法は、例外をスローすることですが、ランタイムがスタックを巻き戻すのに非常にコストがかかり、未定義の動作のデバッグが非常に厄介になる可能性があるため、これはお勧めできません。 (これを覚えておいてください)。

それ以外の場合は、私がお勧めすることは、そのコードを書き直して、ループから抜け出せるようにすることです。このコードを他の方法で変更できない場合は、例外が発生する必要があります...

1
John Leidegren

例外をスローしてループの外でキャッチしますか? 「有害と考えられる」ものを使用してください。

コンピュータサイエンスが自分自身を隅々まで描くと少しおかしいです;-)

0
dwc

簡単な解決策は、検索プロセス全体をメソッドに入れ、回答が得られ次第returnにすることです。

ただし、サンプルコードの抽象的な形式では、他のいくつかの可能性が問題になります。たとえば、ブルートフォースループを使用する必要がないように、コンテンツの一部に「インデックスを付ける」方法があります(例:Mapインスタンスを使用)。

0
joel.neely

Javaはラベル付きブレークをサポートしているという事実は別として、 終了条件に達した場合、C++でfor before timeを終了することは可能ですか? これは他のいくつかの関連するソリューションと同様の質問。

0
ChrisW