33

I have four foreach loops that iterate through the collections and based on a condition do something.

Here is the code that I am writing now:

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

The main object (objects in the code) comes from a third-party provider SDK, so I cannot change anything on that portion. I want to ask the Stack Overflow community if there is a better approach to break all the four foreach loops. Or if there is any other way to refactor this code to make it more readable and maintainable.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
royalghost
  • 2,773
  • 5
  • 23
  • 29

9 Answers9

81

Use a label on the outermost loop, and include this label in the break statement when you want to jump out of all the loops. In the example below, I've modified your code to use the label 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
Fabian Steeg
  • 44,988
  • 7
  • 85
  • 112
Luke Woodward
  • 63,336
  • 16
  • 89
  • 104
  • 4
    This is the correct answer to my question. But, I refactored like other people suggested and moved the logic to a small function and used "return." – royalghost Feb 16 '09 at 14:31
  • Use label Functions only if you don't have another solution. Isn't an good practice. – lucasddaniel Aug 30 '16 at 13:10
20

Extract all the loops into the function and use return.

Alex Reitbort
  • 13,504
  • 1
  • 40
  • 61
6

You could use a labeled break statement. This kind of break terminates an outer statement

See The break Statement

UdayKiran Pulipati
  • 6,579
  • 7
  • 67
  • 92
Pierre
  • 34,472
  • 31
  • 113
  • 192
2

See the Branching Statements Java Tutorial for the easiest way, using a label. You can label any or all of the for loops, then use break or continue in conjunction with those labels.

An alternative to using labels is to use return instead. Just refactor your code into a method call to bypass the need to use labels at all.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
2

Your example is rather generic so it's hard to say what's going on but I'm getting such a a strong code smell from the code you provided that I'm forced to think there has to be another way to do the thing entirely, most likely through refactoring the actual data structure to something more meaningful.

What kind of list objects is? What other (most likely important) data it contains? If it's not too much of a hassle, I'd appreciate if you provided more relevant code since the refactorer in me is getting all giddy just from seeing that pile of loops.

Esko
  • 29,022
  • 11
  • 55
  • 82
1

One way to break, or collapse several statements (actually stack frames) is to throw an exception but this is not recommended because it really expensive for the run-time to unwind the stack and it could lead to really nasty difficult to debug undefined behavior, (keep this in mind).

Otherwise, what I recommend, rewrite that code to be able to break out of the loop in a graceful manner. If you cant change this code in any other way, well then you'll have to result to exceptions...

John Leidegren
  • 59,920
  • 20
  • 131
  • 152
0

Throw an exception and catch it outside the loops? Use something that's "considered harmful?"

It's a bit funny when computer science paints itself into a corner ;-)

dwc
  • 24,196
  • 7
  • 44
  • 55
  • 3
    "Computer science" doesn't "paint itself into a corner". But sometimes programmers make early choices or assumptions that limit their options later on. – joel.neely Feb 15 '09 at 21:11
  • 2
    I think I'm funny. Results may vary. – dwc Feb 15 '09 at 21:18
0

The straightforward solution is to put the entire search process in a method and return as soon as you have an answer.

However, the abstract form of your sample code leaves some other possibilities in question. For instance, is there a way to "index" some of the content (e.g. using Map instances) so that you don't have to use brute-force loops?

joel.neely
  • 30,725
  • 9
  • 56
  • 64
0

Apart from the fact that Java supports labelled break, see also Is it possible to exit a for before time in C++, if an ending condition is reached? which is a similar question with some other relevent solutions.

Community
  • 1
  • 1
ChrisW
  • 54,973
  • 13
  • 116
  • 224