如何在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; } } 

也许有function?

 public void doSomething(List types, List 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 } } } 

根据您的function,您也可以从内循环退出/返回:

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

Java 8 Stream解决方案:

 List types1 = ... List types2 = ... types1.stream() .flatMap(type1 -> types2.stream().map(type2 -> new Type[]{type1, type2})) .filter(types -> /**some condition**/) .findFirst() .ifPresent(types -> /**do something**/); 

您可以在不使用任何标签的情况下从所有循环中断:和标志。

这只是一个棘手的解决方案。

这里condition1是用于从循环K和J中断的条件。而condition2是用于从循环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"); } } 

相反很长一段时间我都在考虑为这类问题分享这种答案。

通常这种情况属于更有意义的逻辑范围,让我们说一些搜索或操纵一些迭代的“for”对象,所以我通常使用函数方法:

 public Object searching(Object[] types) {//or manipulating List typesReferences = new ArrayList(); List typesReferences2 = new ArrayList(); for (Object type : typesReferences) { Object o = getByCriterion(typesReferences2, type); if(o != null) return o; } return null; } private Object getByCriterion(List 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; } 

主要缺点:

  • 大约两倍的线
  • 更多的计算周期消耗,这意味着它从算法的角度来看更慢
  • 更多的打字工作

专业人士:

  • 由于function粒度,关注点分离的比率更高
  • 更高的可重用性和控制搜索/操纵逻辑的比率没有
  • 方法不长,因此它们更紧凑,更容易理解
  • 主观上可读性的比率更高

所以它只是通过不同的方法处理案例。

对这个问题的作者来说基本上是一个问题:你对这种方法有什么看法?

另一个解决方案,没有示例提及(它实际上在prod代码中工作)。

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

如果它在某个函数内部,你为什么不返回它:

 for (Type type : types) { for (Type t : types2) { if (some condition) { return value; } } } 

最好的方法..

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

相当不寻常的方法,但就代码长度( 而不是性能 )而言,这是您可以做的最简单的事情:

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

使用标签。

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

请参阅这篇文章

 boolean broken = false; // declared outside of the loop for efficiency for (Type type : types) { for (Type t : types2) { if (some condition) { broken = true; break; } } if (broken) { break; } } 

我想回答这个问题,但被标记为重复,这也阻止我发布。 所以在这里张贴吧!

如果是新实现,您可以尝试将该逻辑重写为if-else_if-else语句。

 while(keep_going) { if(keep_going && condition_one_holds) { // code } if(keep_going && condition_two_holds) { // code } if(keep_going && condition_three_holds) { // code } if(keep_going && something_goes_really_bad) { keep_going=false; } if(keep_going && condition_four_holds) { // code } if(keep_going && condition_five_holds) { // code } } 

否则,您可以尝试在发生特殊情况时设置标志,并在每个循环条件中检查该标志。

 something_bad_has_happened = false; while(something is true && !something_bad_has_happened){ // code, things happen while(something else && !something_bad_has_happened){ // lots of code, things happens if(something happened){ -> Then control should be returned -> something_bad_has_happened=true; continue; } } if(something_bad_has_happened) { // things below will not be executed continue; } // other things may happen here as well but will not be executed // once control is returned from the inner cycle } HERE! So, while a simple break will not work, it can be made to work using continue. 

如果您只是将逻辑从一种编程语言移植到java,并且只是想让事情正常工作,您可以尝试使用标签

演示breakcontinuelabel

所以java关键字breakcontinue都有默认值,它是“最近的循环”,在使用Java几年后,我刚刚得到它!

它似乎很少用,但很有用。

 import org.junit.Test; /** * Created by cui on 17-5-4. */ public class BranchLabel { @Test public void test() { System.out.println("testBreak"); testBreak(); System.out.println("testBreakLabel"); testBreakLabel(); System.out.println("testContinue"); testContinue(); System.out.println("testContinueLabel"); testContinueLabel(); } /** testBreak a=0,b=0 a=0,b=1 a=1,b=0 a=1,b=1 a=2,b=0 a=2,b=1 a=3,b=0 a=3,b=1 a=4,b=0 a=4,b=1 */ public void testBreak() { for (int a = 0; a < 5; a++) { for (int b = 0; b < 5; b++) { if (b == 2) { break; } System.out.println("a=" + a + ",b=" + b); } } } /** testContinue a=0,b=0 a=0,b=1 a=0,b=3 a=0,b=4 a=1,b=0 a=1,b=1 a=1,b=3 a=1,b=4 a=2,b=0 a=2,b=1 a=2,b=3 a=2,b=4 a=3,b=0 a=3,b=1 a=3,b=3 a=3,b=4 a=4,b=0 a=4,b=1 a=4,b=3 a=4,b=4 */ public void testContinue() { for (int a = 0; a < 5; a++) { for (int b = 0; b < 5; b++) { if (b == 2) { continue; } System.out.println("a=" + a + ",b=" + b); } } } /** testBreakLabel a=0,b=0,c=0 a=0,b=0,c=1 * */ public void testBreakLabel() { anyName: for (int a = 0; a < 5; a++) { for (int b = 0; b < 5; b++) { for (int c = 0; c < 5; c++) { if (c == 2) { break anyName; } System.out.println("a=" + a + ",b=" + b + ",c=" + c); } } } } /** testContinueLabel a=0,b=0,c=0 a=0,b=0,c=1 a=1,b=0,c=0 a=1,b=0,c=1 a=2,b=0,c=0 a=2,b=0,c=1 a=3,b=0,c=0 a=3,b=0,c=1 a=4,b=0,c=0 a=4,b=0,c=1 */ public void testContinueLabel() { anyName: for (int a = 0; a < 5; a++) { for (int b = 0; b < 5; b++) { for (int c = 0; c < 5; c++) { if (c == 2) { continue anyName; } System.out.println("a=" + a + ",b=" + b + ",c=" + c); } } } } } 

for (int j = 0; j < 5; j++) //inner loop应替换for (int j = 0; j < 5 && !exitloops; j++)

在这种情况下,如果condition为True则应退出完整的嵌套循环。 但是如果我们只使用exitloops到上层loop

  for (int i = 0; i < 5 && !exitloops; i++) //upper loop 

然后内部循环将继续,因为没有额外的标志通知此内部循环退出。

示例:如果i = 3j=2则condition为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); } } 

与@ 1800 INFORMATION建议一样,使用将内循环作为外循环条件的条件:

 boolean hasAccess = false; for (int i = 0; i < x && hasAccess == false; i++){ for (int j = 0; j < y; j++){ if (condition == true){ hasAccess = true; break; } } } 

您可以执行以下操作:

  1. 将局部变量设置为false

  2. 当你想要破解时,在第一个循环中将该变量设置为true

  3. 然后你可以检查外循环,是否设置条件然后从外循环中断。

     boolean isBreakNeeded = false; for (int i = 0; i < some.length; i++) { for (int j = 0; j < some.lengthasWell; j++) { //want to set variable if (){ isBreakNeeded = true; break; } if (isBreakNeeded) { break; //will make you break from the outer loop as well } } 

对于某些情况,我们可以while这里有效地使用while循环。

 Random rand = new Random(); // Just an example for (int k = 0; k < 10; ++k) { int count = 0; while (!(rand.nextInt(200) == 100)) { count++; } results[k] = count; } 

甚至为外循环创建一个标志,并在每次执行内循环后检查它是答案。

喜欢这个 :

 for (Type type : types) { boolean flag=false; for (Type t : types2) { if (some condition) { // Do something and break... flag=true; break; // Breaks out of the inner loop } } if(flag) break; } 
 boolean condition = false; for (Type type : types) { for (int i = 0; i < otherTypes.size && !condition; i ++) { condition = true; // if your condition is satisfied } } 

使用条件作为处理完成后的标志。 然后内部循环仅在条件未满足时继续。 无论哪种方式,外部循环将保持chuggin'。

Java没有像C ++那样的gotofunction。 但是, goto仍然是Java中的保留关键字。 他们将来可能会实施它。 对于您的问题,答案是Java中有一些名为label的东西,您可以应用continuebreak语句。 找到下面的代码:

 public static void main(String ...args) { outerLoop: for(int i=0;i<10;i++) { for(int j=10;j>0;j--) { System.out.println(i+" "+j); if(i==j) { System.out.println("Condition Fulfilled"); break outerLoop; } } } System.out.println("Got out of the outer loop"); } 

您只需使用标签来打破内部循环

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

通过检查内部循环的变量,检查内部循环是否通过if语句退出。 您还可以创建另一个变量(如布尔值)来检查内循环是否已退出。

在这个例子中,它使用内部循环的变量来检查它是否已经退出:

 int i, j; for(i = 0; i < 7; i++){ for(j = 0; j < 5; j++) { if (some condition) { // Do something and break... break; // Breaks out of the inner loop } } if(j < 5){ // Checks if inner loop wasn't finished break; // Breaks out of the outer loop } }