如何在双层/嵌套循环中跳出主/外部循环?

39

如果我有一个循环嵌套,在满足某个if语句后,我想要跳出主循环,我该如何做呢?

这是我的代码:

for (int d = 0; d < amountOfNeighbors; d++) {
    for (int c = 0; c < myArray.size(); c++) {
        if (graph.isEdge(listOfNeighbors.get(d), c)) {
            if (keyFromValue(c).equals(goalWord)) { // Once this is true I want to break main loop.
                System.out.println("We got to GOAL! It is "+ keyFromValue(c));
                break; // This breaks the second loop, not the main one.
            }
        }
    }
}

使用一个标签。http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html - Colin D
6个回答

61

太棒了!我学到了新东西。我以为标签已经过时了(还记得GW-BASIC吗?)。我本来会用布尔标志来做这个,但是标签更酷! - ADTC
@ADTC GW-BASIC从未支持文本标签,只支持数字行号(并且需要这些)。如果我没记错的话,微软推出的QuickBASIC添加了对文本标签以及命名子程序的支持。如果维基百科是可信的,那么QBasic肯定包括这样的支持,至少不晚于Visual Basic。 - user

28

您可以为循环添加标签,并使用该 labelled break 来跳出适当的循环:

outer: for (...) {
    inner: for(...) {
        if (someCondition) {
            break outer;
        }
    }
}

查看这些链接获取更多信息:


12
你可以直接从那个函数中 return 控制权。或者使用不太好看的 break labels 方法 :)
如果在你的 for 语句后还有其他代码部分,你可以将循环重构为一个函数。
在面向对象编程中应该避免使用 break 和 continue,因为它们会影响可读性和维护性。当然,在某些情况下它们很方便,但总体来说我们应该避免使用它们,因为它们会鼓励使用 goto 风格的编程。
显然,这种问题的变化经常被发布。在这里 Peter 提供了一些使用标签的好用和奇怪的方法。

2
提供/辩护你的观点,标签是丑陋的。 - John Dvorak
5
在这种情况下,返回可能是合适的。然而标签并不难看,通常也很有用。 - Colin D
2
@JanDvorak 谢谢,这真是丑陋且难以调试。 - dan
2
我通常发现有些编程语言非常难以阅读,原因是其他方面的问题。在具有适当的高阶函数支持和支持性集合API的语言中,我甚至无法回忆起上一次使用需要打破的显式“双重循环”。在我看来,这将更清晰地写成一个“Any”函数。;-) - user166390
3
重新思考编写代码的方式以避免使用标记循环是有益的。之所以许多人不知道它们的存在,是因为我们并不需要它们。我并不是说它们总是不好的。 - Bhesh Gurung
显示剩余4条评论

3

看起来对于Java来说,标记式的break似乎是可行的方法(根据其他答案的共识)。

但对于许多(大多数?)其他语言,或者如果您想避免任何类似于goto的控制流,请设置一个标志:

bool breakMainLoop = false;
for(){
    for(){
        if (some condition){
            breakMainLoop = true;
            break;
        }
    }
    if (breakMainLoop) break;
}

如果在Java中使用标记式break确实是可行的方法,那么在C/C++中使用goto就是可行的方法。 - Evan Harper
此外,问题明确标记为“Java”。 - user
1
这并不改变某人搜索“break nested loop”可能会遇到它的事实。@EvanHarper我同意这种推理方式,但我在Java中花费的时间不多,所以只是按照其他答案的共识去做了。 - Thymine

2

仅供娱乐:

for(int d = 0; d < amountOfNeighbors; d++){
    for(int c = 0; c < myArray.size(); c++){
        ...
            d = amountOfNeighbors;
            break;
        ...
    }
    // No code here
}

关于break label的评论:它是向前goto,可以中断任何语句并跳转到下一个语句:

foo: // Label the next statement (the block)
{
    code ...
    break foo;  // goto [1]
    code ...
}

//[1]

语法错误。缺少分号。 - John Dvorak
哈哈 :) 一定会为这种创意思维点赞。 - Rohit Jain
2
希望没有人会在生产环境中使用这个 :-) - John Dvorak

0

最好的、甚至适合初学者的简单方法:

outerloop:

for(int i=0; i<10; i++){

    // Here we can break the outer loop by:
    break outerloop;

    innerloop:

    for(int i=0; i<10; i++){

        // Here we can break innerloop by:
        break innerloop;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接