如何突破 Java 中的嵌套循环?

我有一个像这样的嵌套循环构造:

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

现在如何摆脱两个循环?我看过类似的问题,但没有一个是 Java 特有的。我无法应用这些解决方案,因为大多数使用的 gotos。

我不想将内部循环使用其他方法。

我不想重新运行循环。中断时,我完成了循环块的执行。

答案

像其他应答者一样,我绝对希望将循环放入另一种方法中,此时您可以返回以完全停止迭代。该答案仅显示了如何满足问题中的要求。

您可以为外部循环使用带有标签的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

从技术上讲,正确的答案是标记外循环。在实践中,如果要在内部循环内的任何位置退出,则最好将代码外部化为方法(如果需要,可以使用静态方法),然后再调用它。

这将提高可读性。

该代码将变成这样:

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);
            }
        }
    }
}

您可以在循环周围使用命名块:

search: {
    for (Type type : types) {
        for (Type t : types2) {
            if (some condition) {
                // Do something and break...
                break search;
            }
        }
    }
}

我从不使用标签。进入这似乎是一个坏习惯。这就是我要做的:

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;
        }
    }
}

您可以使用标签:

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

使用功能:

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;
      }
    }
  }
}

您可以使用一个临时变量:

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;
         }
    }
}

如果您不喜欢breakgoto ,则可以使用 “传统” 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;
        }
    }
}

我需要做类似的事情,但是我选择不使用增强的 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;
        }
    }
}

我更喜欢在循环测试中添加一个明确的 “退出”。任何随便的读者都可以清楚知道循环可能会提前终止。

boolean earlyExit = false;
for(int i = 0 ; i < 10 && !earlyExit; i++) {
     for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; }
}