Как выйти из вложенных циклов в Java?

avatar
boutta
20 мая 2009 в 09:07
1280096
36
1969

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

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

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

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

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

Источник

Ответы (36)

avatar
Jon Skeet
20 мая 2009 в 09:11
2615

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

Вы можете использовать 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
Jon Skeet
20 мая 2009 в 09:15
303

Этот переходит сразу после цикла. Попробуй! Да, метка стоит перед циклом, но это потому, что она маркирует цикл, а не место, в которое вы хотите выйти. (Вы также можете продолжить с меткой.)

avatar
RusJ
17 октября 2020 в 09:02
9

Использование одного ключевого слова 'break' не является подходящим способом, когда вам нужно выйти из более чем одного цикла. Вы можете выйти из немедленного цикла Независимо от того, сколько петель окружает ваше утверждение. Вы можете использовать «перерыв» с меткой! Здесь я использовал метку "abc" Вы можете написать свой код следующим образом в любой функции Java

Этот код показывает, как выйти из самого внешнего цикла

 abc: 
    for (int i = 0; i < 10; i++) { 
        for (int j = 0; j < 10; j++) { 
           for (int k = 0; k < 10; k++) { 
              if (k == 1){
                 break abc;
              } 
        } 
    } 
}

Также вы можете использовать оператор break для выхода из любого цикла во вложенном цикле.

    for (int i = 0; i < 10; i++) { 
       abc:for (int j = 0; j < 10; j++) { 
           for (int k = 0; k < 10; k++) { 
              if (k == 1){
                 break abc;
              } 
        } 
    } 
}

В следующем коде показан пример выхода из самого внутреннего цикла. В других работах после выполнения следующего кода вы оказываетесь за пределами цикла переменных 'k' и все еще внутри цикла переменных 'j' и 'i'.

    for (int i = 0; i < 10; i++) { 
        for (int j = 0; j < 10; j++) { 
           for (int k = 0; k < 10; k++) { 
              if (k == 1){
                 break;
              } 
        } 
    } 
}
avatar
Kiran Maniya
20 сентября 2019 в 11:40
5

Его довольно легко использовать label, Вы можете разорвать внешний цикл от внутреннего с помощью метки, Рассмотрим пример ниже,

public class Breaking{
    public static void main(String[] args) {
        outerscope:
        for (int i=0; i < 5; i++) {
            for (int j=0; j < 5; j++) {
                if (condition) {
                    break outerscope;
                }
            }
        }
    }
}

Другой подход заключается в использовании переменной/флага прерывания для отслеживания необходимого разрыва. рассмотрим следующий пример.

public class Breaking{ 
    public static void main(String[] args) {
        boolean isBreaking = false;
        for (int i=0; i < 5; i++) {
            for (int j=0; j < 5; j++) {
                if (condition) {
                    isBreaking = true;
                    break;
                }
            }
            if(isBreaking){
                break;
            }
        }
    }
}

Однако я предпочитаю использовать первый подход.

avatar
duyuanchao
26 августа 2019 в 12:11
6

Демо

public static void main(String[] args) {
    outer:
    while (true) {
        while (true) {
            break outer;
        }
    }
}
avatar
Deb
8 мая 2019 в 10:20
1

Ниже приведен пример, в котором оператор «break» выталкивает курсор из цикла for всякий раз, когда выполняется условие.

public class Practice3_FindDuplicateNumber {

    public static void main(String[] args) {
        Integer[] inp = { 2, 3, 4, 3, 3 };
        Integer[] aux_arr = new Integer[inp.length];
        boolean isduplicate = false;
        for (int i = 0; i < aux_arr.length; i++) {

            aux_arr[i] = -1;

        }
        outer: for (int i = 0; i < inp.length; i++) {
            if (aux_arr[inp[i]] == -200) {
                System.out.println("Duplicate Found at index: " + i + " Carrying value: " + inp[i]);
                isduplicate = true;
                break outer;
            } else {
                aux_arr[inp[i]] = -200;
            }
        }

        for (Integer integer : aux_arr) {
            System.out.println(integer);
        }

        if (isduplicate == false) {
            System.out.println("No Duplicates!!!!!");
        } else {
            System.out.println("Duplicates!!!!!");
        }
    }

}
avatar
Bishal Jaiswal
4 апреля 2019 в 10:15
9
Концепция

Labeled break используется для разрыва вложенных циклов в java. Пример 1:

loop1:
 for(int i= 0; i<6; i++){
    for(int j=0; j<5; j++){
          if(i==3)
            break loop1;
        }
    }

предположим, что есть 3 цикла, и вы хотите прервать цикл3: Пример 2:

loop3: 
for(int i= 0; i<6; i++){
loop2:
  for(int k= 0; k<6; k++){
loop1:
    for(int j=0; j<5; j++){
          if(i==3)
            break loop3;
        }
    }
}
avatar
Harsh Vardhan
4 августа 2018 в 11:38
2

В Java нет возможности перехода, как в C++. Тем не менее, goto — зарезервированное ключевое слово в Java. Они могут реализовать это в будущем. На ваш вопрос ответ заключается в том, что в Java есть что-то, называемое меткой, к которой вы можете применить оператор continue и break. Найдите код ниже:

public static void main(String ...args) {
    outerLoop: for(int i=0;i<10;i++) {
    for(int j=10;j>0;j--) {
        System.out.println(i+" "+j);
        if(i==j) {
            System.out.println("Condition Fulfilled");
            break outerLoop;
        }
    }
    }
    System.out.println("Got out of the outer loop");
}
avatar
Siddharth Choudhary
19 сентября 2017 в 05:41
1

Вы можете сделать следующее:

  1. установите для локальной переменной значение false

  2. установите эту переменную true в первом цикле, когда вы хотите прервать

  3. тогда вы можете проверить во внешнем цикле, установлено ли условие, а затем выйти из внешнего цикла.

    boolean isBreakNeeded = false;
    for (int i = 0; i < some.length; i++) {
        for (int j = 0; j < some.lengthasWell; j++) {
            //want to set variable if (){
            isBreakNeeded = true;
            break;
        }
    
        if (isBreakNeeded) {
            break; //will make you break from the outer loop as well
        }
    }
    
avatar
Igor Rybak
16 июля 2017 в 10:24
10

Java 8 Stream решение:

List<Type> types1 = ...
List<Type> types2 = ...

types1.stream()
      .flatMap(type1 -> types2.stream().map(type2 -> new Type[]{type1, type2}))
      .filter(types -> /**some condition**/)
      .findFirst()
      .ifPresent(types -> /**do something**/);
Andrei Suvorkov
16 апреля 2019 в 04:32
1

@ TVde1 и по-прежнему полезен для других пользователей, поэтому всегда приветствуются новые методы и решения.

avatar
Bill
4 мая 2017 в 07:41
4

Демонстрация для break, continue и label:

Ключевые слова Java break и continue имеют значение по умолчанию. Это «ближайшая петля», и сегодня, после нескольких лет использования Java, я ее понял!

Кажется, используется редко, но полезно.

import org.junit.Test;

/**
 * Created by cui on 17-5-4.
 */

public class BranchLabel {
    @Test
    public void test() {
        System.out.println("testBreak");
        testBreak();

        System.out.println("testBreakLabel");
        testBreakLabel();

        System.out.println("testContinue");
        testContinue();
        System.out.println("testContinueLabel");
        testContinueLabel();
    }

    /**
     testBreak
     a=0,b=0
     a=0,b=1
     a=1,b=0
     a=1,b=1
     a=2,b=0
     a=2,b=1
     a=3,b=0
     a=3,b=1
     a=4,b=0
     a=4,b=1
     */
    public void testBreak() {
        for (int a = 0; a < 5; a++) {
            for (int b = 0; b < 5; b++) {
                if (b == 2) {
                    break;
                }
                System.out.println("a=" + a + ",b=" + b);
            }
        }
    }

    /**
     testContinue
     a=0,b=0
     a=0,b=1
     a=0,b=3
     a=0,b=4
     a=1,b=0
     a=1,b=1
     a=1,b=3
     a=1,b=4
     a=2,b=0
     a=2,b=1
     a=2,b=3
     a=2,b=4
     a=3,b=0
     a=3,b=1
     a=3,b=3
     a=3,b=4
     a=4,b=0
     a=4,b=1
     a=4,b=3
     a=4,b=4
     */
    public void testContinue() {
        for (int a = 0; a < 5; a++) {
            for (int b = 0; b < 5; b++) {
                if (b == 2) {
                    continue;
                }
                System.out.println("a=" + a + ",b=" + b);
            }
        }
    }

    /**
     testBreakLabel
     a=0,b=0,c=0
     a=0,b=0,c=1
     * */
    public void testBreakLabel() {
        anyName:
        for (int a = 0; a < 5; a++) {
            for (int b = 0; b < 5; b++) {
                for (int c = 0; c < 5; c++) {
                    if (c == 2) {
                        break anyName;
                    }
                    System.out.println("a=" + a + ",b=" + b + ",c=" + c);
                }
            }
        }
    }

    /**
     testContinueLabel
     a=0,b=0,c=0
     a=0,b=0,c=1
     a=1,b=0,c=0
     a=1,b=0,c=1
     a=2,b=0,c=0
     a=2,b=0,c=1
     a=3,b=0,c=0
     a=3,b=0,c=1
     a=4,b=0,c=0
     a=4,b=0,c=1
     */
    public void testContinueLabel() {
        anyName:
        for (int a = 0; a < 5; a++) {
            for (int b = 0; b < 5; b++) {
                for (int c = 0; c < 5; c++) {
                    if (c == 2) {
                        continue anyName;
                    }
                    System.out.println("a=" + a + ",b=" + b + ",c=" + c);
                }
            }
        }
    }
}
avatar
Ravindra HV
1 апреля 2017 в 19:54
2

Если это новая реализация, вы можете попробовать переписать логику в виде операторов if-else_if-else.

while(keep_going) {

    if(keep_going && condition_one_holds) {
        // Code
    }
    if(keep_going && condition_two_holds) {
        // Code
    }
    if(keep_going && condition_three_holds) {
        // Code
    }
    if(keep_going && something_goes_really_bad) {
        keep_going=false;
    }
    if(keep_going && condition_four_holds) {
        // Code
    }
    if(keep_going && condition_five_holds) {
        // Code
    }
}

В противном случае вы можете попробовать установить флаг при возникновении этого особого условия и проверить наличие этого флага в каждом из ваших циклических условий.

something_bad_has_happened = false;
while(something is true && !something_bad_has_happened){
    // Code, things happen
    while(something else && !something_bad_has_happened){
        // Lots of code, things happens
        if(something happened){
            -> Then control should be returned ->
            something_bad_has_happened=true;
            continue;
        }
    }
    if(something_bad_has_happened) { // The things below will not be executed
        continue;
    }

    // Other things may happen here as well, but they will not be executed
    //  once control is returned from the inner cycle.
}

ЗДЕСЬ! Таким образом, хотя простой разрыв не сработает, его можно заставить работать с помощью continue.

.

Если вы просто переносите логику с одного языка программирования на Java и просто хотите, чтобы все заработало, вы можете попробовать использовать метки.

avatar
Dharmik Patel
24 марта 2017 в 01:43
1

В некоторых случаях здесь можно эффективно использовать цикл while.

Random rand = new Random();
// Just an example
for (int k = 0; k < 10; ++k) {
    int count = 0;
    while (!(rand.nextInt(200) == 100)) {
       count++;
    }

    results[k] = count;
}
avatar
Chit Khine
25 августа 2016 в 11:25
5

Если он находится внутри какой-то функции, почему бы вам просто не вернуть его:

for (Type type : types) {
    for (Type t : types2) {
         if (some condition) {
            return value;
         }
    }
}
Bill K
2 декабря 2017 в 00:34
0

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

avatar
Vikrant Kashyap
8 апреля 2016 в 04:29
3

for (int j = 0; j < 5; j++) //inner loop следует заменить на for (int j = 0; j < 5 && !exitloops; j++).

Здесь, в этом случае следует выйти из полных вложенных циклов, если условие равно True . Но если мы используем exitloops только для верхнего loop

 for (int i = 0; i < 5 && !exitloops; i++) //upper loop

Затем внутренний цикл продолжится, потому что нет дополнительного флага, уведомляющего о завершении этого внутреннего цикла.

Пример: если i = 3 и j=2, то условие равно false. Но в следующей итерации внутреннего цикла j=3 условие (i*j) становится 9, что равно true, но внутренний цикл будет продолжаться до тех пор, пока j не станет 5.

Таким образом, он должен использовать exitloops и во внутренних циклах.

boolean exitloops = false;
for (int i = 0; i < 5 && !exitloops; i++) { //here should exitloops as a Conditional Statement to get out from the loops if exitloops become true. 
    for (int j = 0; j < 5 && !exitloops; j++) { //here should also use exitloops as a Conditional Statement. 
        if (i * j > 6) {
            exitloops = true;
            System.out.println("Inner loop still Continues For i * j is => "+i*j);
            break;
        }
        System.out.println(i*j);
    }
}
avatar
Dhawan Gayash
31 марта 2016 в 18:33
-10

Я чувствую, что использование меток делает код очень похожим на оператор goto. Это просто мысль.

Вместо этого создайте исключение во внутреннем цикле for и инкапсулируйте два цикла for блоком try catch.

Что-то вроде

try {
  // ...
  for(Object outerForLoop : objectsOuter) {
     // ...
     for (Object innerForLoop : objectsInner) {
        // ...
        if (isConditionTrue)
             throw new WrappedException("With some useful message. Probably some logging as well.");
     }
  }
  catch (WrappedException) {
        // Do something awesome or just don't do anything to swallow the exception.
  }

Просто подумал. Я предпочитаю этот код, так как он дает мне лучшую логгируемость (например, это слово) для меня, когда он запускается в производстве или что-то в этом роде.

boutta
1 апреля 2016 в 06:42
10

Использование исключений для потока управления не совсем лучшая практика. Так что нет, это не вариант.

Neuron
20 апреля 2018 в 16:30
0

@boutta что заставляет тебя так думать?

boutta
22 апреля 2018 в 13:18
1

Много чтений и мнения некоторых пользующихся большим доверием людей, таких как дядя Боб или Мартин Фаулер.

Alvaro
29 апреля 2019 в 13:30
0

Я знаю, что этот вопрос касается конкретно java, но некоторые люди приняли решение сделать это в языковом дизайне, это именно то, для чего предназначен StopIteration python.

avatar
Oleksii Kyslytsyn
28 января 2016 в 18:53
9

Обычно в таких случаях это происходит в рамках более осмысленной логики, скажем, поиска или манипулирования некоторыми из итерируемых рассматриваемых объектов for, поэтому я обычно использую функциональный подход:

public Object searching(Object[] types) { // Or manipulating
    List<Object> typesReferences = new ArrayList<Object>();
    List<Object> typesReferences2 = new ArrayList<Object>();

    for (Object type : typesReferences) {
        Object o = getByCriterion(typesReferences2, type);
        if(o != null) return o;
    }
    return null;
}

private Object getByCriterion(List<Object> typesReferences2, Object criterion) {
    for (Object typeReference : typesReferences2) {
        if(typeReference.equals(criterion)) {
             // here comes other complex or specific logic || typeReference.equals(new Object())
             return typeReference;
        }
    }
    return null;
}

Основные минусы:

  • примерно вдвое больше строк
  • большее потребление вычислительных циклов, что означает медленнее с алгоритмической точки зрения
  • еще печатать

Плюсы:

  • более высокий коэффициент разделения проблем из-за функциональной детализации
  • более высокий коэффициент повторного использования и контроля логика поиска/манипулирования без
  • методы не длинные, поэтому они компактнее и легче для понимания
  • более высокий коэффициент удобочитаемости

Таким образом, это просто другой подход к делу.

Вопрос к автору этого вопроса: что вы думаете об этом подходе?

avatar
Keshav bansal
23 августа 2015 в 21:04
6

Лучший и простой способ..

outerloop:
for(int i=0; i<10; i++){
    // here we can break Outer loop by 
    break outerloop;

    innerloop:
    for(int i=0; i<10; i++){
        // here we can break innerloop by 
        break innerloop;
     }
}
Neuron
26 октября 2015 в 03:05
4

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

Taslim Oseni
12 января 2018 в 10:36
0

Я собирался напечатать то же самое. Этикетки в данном случае несколько бесполезны.

avatar
user2875404
25 апреля 2015 в 22:01
5

Довольно необычный подход, но с точки зрения длины кода (не производительности) проще всего это сделать:

for(int i = 0; i++; i < j) {
    if(wanna exit) {
        i = i + j; // if more nested, also add the 
                   // maximum value for the other loops
    }
}
avatar
ursa
10 октября 2014 в 13:57
5

Еще одно решение, упомянутое без примера (оно действительно работает в производственном коде).

try {
    for (Type type : types) {
        for (Type t : types2) {
            if (some condition #1) {
                // Do something and break the loop.
                throw new BreakLoopException();
            }
        }
    }
}
catch (BreakLoopException e) {
    // Do something on look breaking.
}

Конечно, BreakLoopException должен быть внутренним, частным и ускоренным без трассировки стека:

private static class BreakLoopException extends Exception {
    @Override
    public StackTraceElement[] getStackTrace() {
        return new StackTraceElement[0];
    }
}
vefthym
10 октября 2014 в 14:09
1

На самом деле это было упомянуто в ответе, получившем -23 голоса ... coderhelper.com/a/886980/2516301 . Это сделает работу, но это очень плохая практика программирования...

ursa
10 октября 2014 в 14:22
0

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

Bill K
2 декабря 2017 в 00:37
1

Было бы еще читабельнее, если бы его разбили на отдельный вызов функции с возвратом по центру. Часто делается еще лучше за счет небольшого рефакторинга, поэтому имеет смысл как автономная (часто повторно используемая) функция.

avatar
mtyson
13 сентября 2014 в 19:00
2

Как и в предложении @1800 INFORMATION, используйте условие, разрывающее внутренний цикл, как условие внешнего цикла:

boolean hasAccess = false;
for (int i = 0; i < x && hasAccess == false; i++){
    for (int j = 0; j < y; j++){
        if (condition == true){
            hasAccess = true;
            break;
        }
    }
}
avatar
ddyer
4 августа 2014 в 17:29
11

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

boolean earlyExit = false;
for(int i = 0 ; i < 10 && !earlyExit; i++) {
     for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; }
}
avatar
astryk
11 июля 2014 в 16:46
1
boolean condition = false;
for (Type type : types) {
    for (int i = 0; i < otherTypes.size && !condition; i ++) {
        condition = true; // If your condition is satisfied
    }
}

Используйте condition в качестве флага завершения обработки. Затем внутренний цикл продолжается только до тех пор, пока условие не выполнено. В любом случае внешний цикл будет продолжаться.

avatar
Rumesh Eranga Hapuarachchi
1 июня 2014 в 12:41
7

Использовать ярлыки.

INNER:for(int j = 0; j < numbers.length; j++) {
    System.out.println("Even number: " + i + ", break  from INNER label");
    break INNER;
}

См. эту статью

avatar
Hitendra Solanki
21 мая 2014 в 14:33
8

Вы можете выйти из всех циклов без использования каких-либо меток: и флагов.

Это просто сложное решение.

Здесь условие1 — это условие, которое используется для выхода из цикла K и J. А условие2 — это условие, которое используется для выхода из цикла K, J и I.

Например:

public class BreakTesting {
    public static void main(String[] args) {
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                for (int k = 0; k < 9; k++) {
                    if (condition1) {
                        System.out.println("Breaking from Loop K and J");
                        k = 9;
                        j = 9;
                    }
                    if (condition2) {
                        System.out.println("Breaking from Loop K, J and I");
                        k = 9;
                        j = 9;
                        i = 9;
                    }
                }
            }
        }
        System.out.println("End of I , J , K");
    }
}
Willi Mentzel
4 июля 2015 в 11:18
2

Как бы я использовал это с циклами for-each? ;)

Neuron
26 октября 2015 в 03:06
5

Это не работает, если у вас есть более сложное условие цикла, например list.size()>5. Кроме того, это действительно просто взлом. Это трудно читать и плохая практика!

Florian F
25 августа 2018 в 20:07
0

Это подвержено ошибкам. Представьте, что вы изменили внутренний цикл на (int k = 0; k < 10; k++) и не исправили все k = 9 на k = 10. Вы можете попасть в бесконечный цикл.

avatar
zord
21 декабря 2013 в 22:56
17

Если вам не нравятся breaks и gotos, вы можете использовать "традиционный" цикл 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;
        }
    }
}
John McClane
5 декабря 2018 в 00:00
3

Не подходит для циклов foreach.

Quintec
7 декабря 2018 в 01:03
3

@JohnMcClane И вы рассылаете это по многим ответам на вопрос 9+ летней давности, потому что ...?

avatar
Panzercrisis
11 сентября 2013 в 22:14
5
boolean broken = false; // declared outside of the loop for efficiency
for (Type type : types) {
    for (Type t : types2) {
        if (some condition) {
            broken = true;
            break;
        }
    }

    if (broken) {
        break;
    }
}
avatar
Edd
7 мая 2013 в 18:57
0

Проверить выход из внутреннего цикла с помощью оператора if, проверив переменную внутреннего цикла. Вы также можете создать другую переменную, такую ​​как логическое значение, чтобы проверить, вышел ли внутренний цикл.

В этом примере используется переменная внутреннего цикла для проверки выхода из него:

int i, j;
for(i = 0; i < 7; i++){

for(j = 0; j < 5; j++) {

     if (some condition) {
         // Do something and break...
         break; // Breaks out of the inner loop
     }
}
     if(j < 5){    // Checks if inner loop wasn't finished
     break;    // Breaks out of the outer loop   
     } 
}
avatar
voidMainReturn
28 апреля 2013 в 05:08
1

Даже создание флага для внешнего цикла и проверка этого после каждого выполнения внутреннего цикла может быть ответом.

Вот так:

for (Type type : types) {
    boolean flag=false;
    for (Type t : types2) {
        if (some condition) {
            // Do something and break...
            flag=true;
            break; // Breaks out of the inner loop
        }
    }
    if(flag)
        break;
}
avatar
Mahesh Peri
17 октября 2012 в 11:50
1

Вы просто используете метку для разрыва внутренних циклов

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");
}
}
avatar
Swifty McSwifterton
5 февраля 2012 в 06:04
13

Мне нужно было сделать нечто подобное, но я решил не использовать для этого расширенный цикл 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;
        }
    }
}
boutta
29 января 2016 в 07:58
0

Я не считаю крутым перебирать все элементы после нарушения условия. Таким образом, я бы добавил перерыв в случае else.

Swifty McSwifterton
31 июля 2016 в 16:53
0

@boutta Я не знаю, как ты пришел к такому выводу. Как только условие истинно, оба цикла выходят.

boutta
10 ноября 2016 в 08:56
0

Хорошо, я не понял часть с манипулированием 's' var. Но я нахожу такой плохой стиль, поскольку s представляет размер. Тогда я предпочитаю ответ от ddyer с явными переменными: coderhelper.com/a/25124317/15108

Zsolti
27 сентября 2017 в 12:44
0

@boutta Вы можете изменить s на значение, которое меньше, чем i, или изменить i на значение, большее или равное, чем s, и то и другое должно сработать. Вы правы насчет изменения s, потому что его можно использовать в другом месте позже, но изменение i не повредит, просто убедитесь, что первый for не будет продолжать зацикливаться.

avatar
Elle Mundy
7 декабря 2011 в 17:52
150

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

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;
        }
    }
}
avatar
Zo72
14 ноября 2011 в 18:26
424

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

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

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

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);
            }
        }
    }
}
Haoest
7 декабря 2011 в 01:15
35

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

avatar
Fortega
20 мая 2009 в 11:43
44

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

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;
      }
    }
  }
}
avatar
Joey
20 мая 2009 в 09:12
230

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

search: {
    for (Type type : types) {
        for (Type t : types2) {
            if (some condition) {
                // Do something and break...
                break search;
            }
        }
    }
}
Jon Skeet
20 мая 2009 в 09:13
43

Вам не нужно создавать новый блок, чтобы использовать метку.

Bombe
20 мая 2009 в 09:24
90

Нет, но это делает намерение намного яснее. Смотрите первый комментарий к принятому ответу.

avatar
Miguel Ping
20 мая 2009 в 09:11
24

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

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;
         }
    }
}
avatar
simon622
20 мая 2009 в 09:11
120

Можно использовать ярлыки:

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