Как вырваться из вложенных циклов в Java? - PullRequest
1689 голосов
/ 20 мая 2009

У меня есть конструкция с вложенным циклом:

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

Теперь, как мне вырваться из обеих петель? Я смотрел на похожие вопросы, но ни один из них не касается конкретно Java. Я не мог применить эти решения, потому что большинство использовало gotos.

Я не хочу помещать внутренний цикл в другой метод.

Я не хочу перезапускать циклы. При разрыве я заканчиваю выполнение блока цикла.

Ответы [ 33 ]

2252 голосов
/ 20 мая 2009

Как и другие ответчики, я бы определенно предпочел бы поместить циклы в другой метод, после чего вы можете просто вернуться, чтобы полностью прекратить итерации. Этот ответ просто показывает, как могут быть выполнены требования в вопросе.

Вы можете использовать break с меткой для внешнего цикла. Например:

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");
    }
}

Это печатает:

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
382 голосов
/ 14 ноября 2011

Технически правильный ответ - обозначить внешний цикл. На практике, если вы хотите выйти в любой точке внутреннего цикла, вам лучше было бы перенести код в метод (статический метод, если необходимо), а затем вызвать его.

Это окупится за удобочитаемость.

Код станет примерно таким:

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

Соответствует примеру для принятого ответа:

 public class Test {
    public static void main(String[] args) {
        loop();
        System.out.println("Done");
    }

    public static void loop() {
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                if (i * j > 6) {
                    System.out.println("Breaking");
                    return;
                }
                System.out.println(i + " " + j);
            }
        }
    }
}
205 голосов
/ 20 мая 2009

Вы можете использовать именованный блок вокруг циклов:

search: {
    for (Type type : types) {
        for (Type t : types2) {
            if (some condition) {
                // Do something and break...
                break search;
            }
        }
    }
}
123 голосов
/ 07 декабря 2011

Я никогда не использую ярлыки. Кажется, это плохая практика. Вот что я бы сделал:

boolean finished = false;
for (int i = 0; i < 5 && !finished; i++) {
    for (int j = 0; j < 5; j++) {
        if (i * j > 6) {
            finished = true;
            break;
        }
    }
}
93 голосов
/ 20 мая 2009

Вы можете использовать метки:

label1: 
for (int i = 0;;) {
    for (int g = 0;;) {
      break label1;
    }
}
34 голосов
/ 20 мая 2009

Используйте функцию:

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;
      }
    }
  }
}
15 голосов
/ 20 мая 2009

Вы можете использовать временную переменную:

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
         }
    }
}

В зависимости от вашей функции вы также можете выйти / вернуться из внутреннего цикла:

for (Type type : types) {
    for (Type t : types2) {
         if (some condition) {
             // Do something and break...
             return;
         }
    }
}
11 голосов
/ 22 декабря 2013

Если вам не нравятся break s и goto s, вы можете использовать «традиционный» цикл for вместо for-in с дополнительным условием прерывания:

int a, b;
bool abort = false;
for (a = 0; a < 10 && !abort; a++) {
    for (b = 0; b < 10 && !abort; b++) {
        if (condition) {
            doSomeThing();
            abort = true;
        }
    }
}
10 голосов
/ 05 февраля 2012

Мне нужно было сделать подобное, но я решил не использовать расширенный цикл for, чтобы сделать это.

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;
        }
    }
}
8 голосов
/ 04 августа 2014

Я предпочитаю добавить явный «выход» к тестам цикла. Это дает понять любой случайный читатель, что цикл может закончиться рано.

boolean earlyExit = false;
for(int i = 0 ; i < 10 && !earlyExit; i++) {
     for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...