views:

4685

answers:

9

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 stackoverflow community if there is a better approach to break all the four foreach loop. Or if there is any other way to refactor this code to make it more readable and maintainable. Thanks.

A: 

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
"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
I think I'm funny. Results may vary.
dwc
Results may vary. rofl.
Alex Baranosky
A: 

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
Java does support labels, but they can only be used with break and continue statements.
Pourquoi Litytestdata
+8  A: 

Extract all the loops into the function and use return.

Alex Reitbort
The code as shown is not nice: refactoring along these lines would be much better.
Fortyrunner
this is the preferred way over using break labels, unless you know it is clearer to use break.
Chii
Introducing a method boundary in an arbitrary place is "the preferred way"?
Tom Hawtin - tackline
It is better then using labels
Alex Reitbort
+21  A: 

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
Pourquoi Litytestdata
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
+4  A: 

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

See http://java.sun.com/docs/books/tutorial/java/nutsandbolts/branch.html

Pierre
A: 

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
A: 

Apart from the fact that Java supports labelled break, see also http://stackoverflow.com/questions/416464/is-it-possible-to-exit-a-for-before-time-in-c-if-an-ending-condition-is-reache which is a similar question with some other relevent solutions.

ChrisW
+1  A: 

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
A: 

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