Tuesday, May 29, 2012

Breaking out of nested loops in Java


I've got a nested loop construct like this:




for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break; // Breaks out of the inner loop
}
}
}



Now how can I break out of both loops. I've looked at similar questions, but none concerns Java specifically. I couldn't apply these solutions because most used gotos.



I don't want to put the inner loop in a different method.



Update: I don't want to rerun the loops, when breaking I'm finished with the execution of the loop block.


Source: Tips4all

9 comments:

  1. You can use break with a label for the outer loop. For example:

    public class Test {
    public static void main(String[] args) {
    outerloop:
    for (int i=0; i < 5; i++) {
    for (int j=0; j < 5; j++) {
    if (i * j > 6) {
    System.out.println("Breaking");
    break outerloop;
    }
    System.out.println(i + " " + j);
    }
    }
    System.out.println("Done");
    }
    }


    This prints:

    0 0
    0 1
    0 2
    0 3
    0 4
    1 0
    1 1
    1 2
    1 3
    1 4
    2 0
    2 1
    2 2
    2 3
    Breaking
    Done

    ReplyDelete
  2. Technically the correct answer is to label the outer loop. In practice if you want to exit at any point inside an inner loop then you would be better off externalizing the code into a method (a static method if needs be) and then call it.

    That would pay off for readability.

    The code would become something like that:

    private static String search(...)
    {
    for (Type type : types) {
    for (Type t : types2) {
    if (some condition) {
    // Do something and break...
    return search;
    }
    }
    }
    return null;
    }

    ReplyDelete
  3. You can use a named block around the loops:

    search: {
    for (Type type : types) {
    for (Type t : types2) {
    if (some condition) {
    // Do something and break...
    break search;
    }
    }
    }
    }

    ReplyDelete
  4. you can use labels;



    label1 : for(int i =0;;)
    {
    for(int g =0;;)
    {
    break label1;
    }
    }

    ReplyDelete
  5. maybe with a function?

    public void doSomething(List<Type> types, List<Type> types2){
    for(Type t1 : types){
    for (Type t : types2) {
    if (some condition) {
    //do something and return...
    return;
    }
    }
    }
    }

    ReplyDelete
  6. I never use labels. It seems like a bad practice to get into. Here's what I would do:

    bool finished;
    for (int i = 0; i < 5 || finished; i++) {
    for (int j = 0; j < 5; j++) {
    if (i * j > 6) {
    finished = true;
    break;
    }
    }
    }

    ReplyDelete
  7. You can use a temporary variable:

    boolean outerBreak = false;
    for (Type type : types) {
    if(outerBreak) break;
    for (Type t : types2) {
    if (some condition) {
    // Do something and break...
    outerBreak = true;
    break; // Breaks out of the inner loop
    }
    }
    }


    Depending on your function, you can also exit/return from the inner loop:

    for (Type type : types) {
    for (Type t : types2) {
    if (some condition) {
    // Do something and break...
    return;
    }
    }
    }

    ReplyDelete
  8. I needed to do a similar thing, but I chose not to use the enhanced for loop to do it.

    int s = type.size();
    for (int i = 0; i < s; i++) {
    for (int j = 0; j < t.size(); j++) {
    if (condition) {
    // do stuff after which you want
    // to completely break out of both loops
    s = 0; // enables the main loop to terminate
    break;
    }
    }
    }

    ReplyDelete
  9. You can throw an exception, or repeat the inner loop condition in the outer loop.

    ReplyDelete