«1. Обзор

В этом уроке мы создадим несколько примеров, чтобы показать различные способы использования разрыва в цикле. Далее мы также увидим, как завершить цикл вообще без использования break.

2. Проблема

Вложенные циклы очень полезны, например, для поиска в списке списков.

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

Сначала мы пройдемся по списку студентов. Затем внутри этого цикла мы перебирали список запланированных курсов.

Когда мы напечатаем имена студентов и курсов, мы получим следующий результат:

student 0
  course 0
  course 1
student 1
  course 0
  course 1

Мы хотели найти первого студента, который запланировал курс 0. Однако, если мы просто используем циклы, то приложение продолжить поиск после того, как курс будет найден.

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

3. Прерывание

Первый вариант выхода из вложенного цикла — это просто использовать оператор break:

String result = "";
for (int outerCounter = 0; outerCounter < 2; outerCounter++) {
    result += "outer" + outerCounter;
    for (int innerCounter = 0; innerCounter < 2; innerCounter++) {
        result += "inner" + innerCounter;
        if (innerCounter == 0) {
            break;
        }
    }
}
return result;

У нас есть внешний цикл и внутренний цикл, оба цикла имеют две итерации. . Если счетчик внутреннего цикла равен 0, мы выполняем команду break. Когда мы запустим пример, он покажет следующий результат:

outer0inner0outer1inner0

Или мы могли бы изменить код, чтобы сделать его более читабельным:

outer 0
  inner 0
outer 1
  inner 0

Это то, что мы хотим?

Почти внутренний цикл завершается оператором break после нахождения 0. Однако внешний цикл продолжается, а это не то, что нам нужно. Мы хотим полностью прекратить обработку, как только получим ответ.

4. Labeled Break

Предыдущий пример был шагом в правильном направлении, но нам нужно его немного улучшить. Мы можем сделать это, используя помеченный разрыв:

String result = "";
myBreakLabel:
for (int outerCounter = 0; outerCounter < 2; outerCounter++) {
    result += "outer" + outerCounter;
    for (int innerCounter = 0; innerCounter < 2; innerCounter++) {
        result += "inner" + innerCounter;
        if (innerCounter == 0) {
            break myBreakLabel;
        }
    }
}
return result;

Помеченный разрыв завершит внешний цикл, а не только внутренний цикл. Мы достигаем этого, добавляя myBreakLabel вне цикла и изменяя оператор break, чтобы остановить myBreakLabel. После того, как мы запустим пример, мы получим следующий результат:

outer0inner0

Мы можем прочитать его немного лучше с некоторым форматированием:

outer 0
  inner 0

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

5. Возврат

В качестве альтернативы мы могли бы также использовать оператор return для прямого возврата результата, когда он найден:

String result = "";
for (int outerCounter = 0; outerCounter < 2; outerCounter++) {
    result += "outer" + outerCounter;
    for (int innerCounter = 0; innerCounter < 2; innerCounter++) {
        result += "inner" + innerCounter;
        if (innerCounter == 0) {
            return result;
        }
    }
}
return "failed";

Метка удаляется, а оператор break заменяется оператором return.

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

6. Заключение

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

В качестве альтернативы мы можем использовать оператор return. Использование возврата делает код более читабельным и менее подверженным ошибкам, поскольку нам не нужно думать о разнице между немаркированными и помеченными разрывами.

Не стесняйтесь взглянуть на код на GitHub.