Как вырваться из вложенных циклов в 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 ]

7 голосов
/ 16 июля 2017

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**/);
5 голосов
/ 21 мая 2014

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

Это просто хитрое решение.

Здесь условие 1 - это условие, которое используется для выхода из цикла К и 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");
    }
}
5 голосов
/ 28 января 2016

Обычно в таких случаях это входит в сферу более значимой логики, скажем, некоторого поиска или манипулирования некоторыми итеративными объектами 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;
}

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

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

Плюсы:

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

Так что это просто обработка дела с помощью другого подхода.

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

3 голосов
/ 25 августа 2016

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

for (Type type : types) {
    for (Type t : types2) {
         if (some condition) {
            return value;
         }
    }
}
3 голосов
/ 24 августа 2015

Лучший и простой метод ..

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;
     }
}
3 голосов
/ 26 апреля 2015

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

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
    }
}
3 голосов
/ 10 октября 2014

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

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];
    }
}
3 голосов
/ 04 апреля 2019

Помеченный разрыв концепция используется для разрыва вложенных циклов в 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;
        }
    }
}
3 голосов
/ 01 июня 2014

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

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

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

2 голосов
/ 08 апреля 2016

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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...