Breaking Out of Nested Loops – 打破嵌套循环

最后修改: 2019年 7月 1日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll create some examples to show different ways to use break within a loop. Next, we’ll also see how to terminate a loop without using break at all.

在本教程中,我们将创建一些例子来展示在循环中使用break的不同方法。接下来,我们还将看到如何在完全不使用break的情况下终止一个循环。

2. The Problem

2.问题

Nested loops are very useful, for instance, to search in a list of lists.

嵌套循环是非常有用的,例如,在一个列表中搜索。

One example would be a list of students, where each student has a list of planned courses. Let’s say we want to find the name of one person that planned course 0.

一个例子是一个学生列表,每个学生都有一个计划课程的列表。假设我们想找到一个计划了课程0的人的名字。

First, we’d loop over the list of students. Then, inside that loop, we’d loop over the list of planned courses.

首先,我们要在学生名单上进行循环。然后,在这个循环中,我们会在计划中的课程列表上循环。

When we print the names of the students and courses we’ll get the following result:

当我们打印学生和课程的名字时,我们会得到以下结果。

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

We wanted to find the first student that planned course 0. However, if we just use loops then the application will continue searching after the course is found.

我们想找到第一个计划课程0的学生。然而,如果我们只是使用循环,那么应用程序将在找到课程后继续搜索。

After we find a person who planned the specific course, we want to stop searching. Continuing to search would take more time and resources while we don’t need the extra information. That’s why we want to break out of the nested loop.

在我们找到一个计划特定课程的人之后,我们想停止搜索。继续搜索会花费更多的时间和资源,而我们却不需要额外的信息。这就是为什么我们要打破嵌套循环。

3. Break

3.休息

The first option we have to go out of a nested loop is to simply use the break statement:

我们走出嵌套循环的第一个选择是简单地使用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;

We have an outer loop and an inner loop, both loops have two iterations. If the counter of the inner loop equals 0 we execute the break command. When we run the example, it will show the following result:

我们有一个外循环和一个内循环,两个循环都有两个迭代。如果内循环的计数器等于0,我们就执行break命令。当我们运行这个例子时,它将显示以下结果。

outer0inner0outer1inner0

Or we could adjust the code to make it a bit more readable:

或者我们可以调整代码,使其更容易阅读。

outer 0
  inner 0
outer 1
  inner 0

Is this what we want?

这就是我们想要的吗?

Almost, the inner loop is terminated by the break statement after 0 is found. However, the outer loop continues, which is not what we want. We want to stop processing completely as soon as we have the answer.

几乎,内循环被break语句终止了在找到0之后。然而,外循环继续进行,这不是我们想要的。我们想在得到答案后立即完全停止处理。

4. Labeled Break

4.标记的休息

The previous example was a step in the right direction, but we need to improve it a bit. We can do that by using a 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;

A labeled break will terminate the outer loop instead of just the inner loop. We achieve that by adding the myBreakLabel outside the loop and changing the break statement to stop myBreakLabel. After we run the example we get the following result:

一个标记的中断将终止外循环,而不仅仅是内循环。我们通过在循环外添加myBreakLabel并将中断语句改为stopmyBreakLabel来实现。在我们运行这个例子后,我们得到以下结果。

outer0inner0

We can read it a bit better with some formatting:

我们可以用一些格式化的方式来阅读它,这样会更好一些。

outer 0
  inner 0

If we look at the result we can see that both the inner loop and the outer loop are terminated, which is what we wanted to achieve.

如果我们看一下结果,我们可以看到内循环和外循环都被终止了,这就是我们想要实现的。

5. Return

5.返回

As an alternative, we could also use the return statement to directly return the result when it’s found:

作为一种选择,我们也可以使用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";

The label is removed and the break statement is replaced by a return statement.

标签被删除,break语句被return语句取代。

When we execute the code above we get the same result as for the labeled break. Note that for this strategy to work, we typically need to move the block of loops into its own method.

当我们执行上面的代码时,我们得到的结果与标注的break相同。注意,为了使这一策略奏效,我们通常需要将循环块移到它自己的方法中。

6. Conclusion

6.结语

So, we’ve just looked at what to do when we need to exit early from a loop, like when we’ve found the item we’re searching for. The break keyword is helpful for single loops, and we can use labeled breaks for nested loops.

所以,我们刚刚看了当我们需要从一个循环中提前退出时该怎么做,比如当我们找到了我们要搜索的项目时。break关键字对单个循环很有帮助,我们可以使用标记的breaks来处理嵌套循环。

Alternatively, we can use a return statement. Using return makes the code better readable and less error-prone as we don’t have to think about the difference between unlabeled and labeled breaks.

另外,我们可以使用return语句。使用return使代码的可读性更好,而且不容易出错,因为我们不必考虑无标记和有标记的中断之间的区别。

Feel free to have a look at the code over on GitHub.

请随意看看GitHub上的代码