如何在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。

我不想把内循环放在不同的方法中。

我不想返回循环。当中断时,我完成了循环块的执行。

1348967 次浏览

像其他回答者一样,我肯定会更喜欢将循环放在不同的方法中,此时你可以返回以完全停止迭代。这个答案只是展示了如何满足问题中的要求。

您可以将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 00 10 20 30 41 01 11 21 31 42 02 12 22 3BreakingDone

您可以使用标签:

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

您可以使用临时变量:

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

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

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

使用一个函数:

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

从技术上讲,正确的答案是标记外部循环。在实践中,如果你想在内部循环内的任何一点退出,那么你最好将代码外部化为一个方法(如果需要,一个静态方法),然后调用它。

这将支付易读性。

代码会变成这样:

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

我从不使用标签。这似乎是一种不好的做法。我会这样做:

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

我需要做类似的事情,但我选择不使用增强的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 loopss = 0; // enables the _main_ loop to terminatebreak;}}}

你只是用标签来打破内部循环

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

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

像这样:

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

通过检查内部循环的变量来检查是否使用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 finishedbreak;    // Breaks out of the outer loop}}
boolean broken = false; // declared outside of the loop for efficiencyfor (Type type : types) {for (Type t : types2) {if (some condition) {broken = true;break;}}
if (broken) {break;}}

如果您不喜欢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;}}}

您可以从所有循环中断,而无需使用任何标签:和标志。

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

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

使用标签。

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

参考这篇文章

boolean condition = false;for (Type type : types) {for (int i = 0; i < otherTypes.size && !condition; i ++) {condition = true; // If your condition is satisfied}}

使用condition作为处理完成时的标志。然后,只有在条件未满足时,内循环才会继续。无论哪种方式,外层循环都将继续进行。

我更喜欢在循环测试中添加一个明确的“退出”。它清楚地表明任何偶然的读者,循环可能会提前终止。

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

像@1800信息建议,使用中断内部循环的条件作为外部循环的条件:

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

另一个解决方案,没有例子(它实际上在产品代码中工作)。

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应该是内部的,私有的,并使用no-stack-trac进行加速:

private static class BreakLoopException extends Exception {@Overridepublic StackTraceElement[] getStackTrace() {return new StackTraceElement[0];}}

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

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

最好的和简单的方法。

outerloop:for(int i=0; i<10; i++){// here we can break Outer loop bybreak outerloop;
innerloop:for(int i=0; i<10; i++){// here we can break innerloop bybreak innerloop;}}

通常在这种情况下,它会进入更有意义的逻辑范围,比方说对一些迭代的“for”对象进行一些搜索或操作,所以我通常使用函数方法:

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

主要缺点:

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

优点:

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

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

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

我觉得使用标签使代码看起来很像goto语句。这只是一个想法。

相反,在内部for循环中抛出一个异常,并用try cat块封装两个for循环。

就像

try {// ...for(Object outerForLoop : objectsOuter) {// ...for (Object innerForLoop : objectsInner) {// ...if (isConditionTrue)throw new WrappedException("With some useful message. Probably some logging as well.");}}catch (WrappedException) {// Do something awesome or just don't do anything to swallow the exception.}

只是一个想法。我更喜欢这段代码,因为当它在生产环境或其他地方运行时,它为我提供了更好的可记录性(就像这个词一样)。

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

在这里,在这种情况下,如果条件为True,则应该退出完整的嵌套循环。但是如果我们只对上面的loop使用exitloops

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

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

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

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

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

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

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

如果它是一个新的实现,您可以尝试将逻辑重写为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 happenwhile(something else && !something_bad_has_happened){// Lots of code, things happensif(something happened){-> Then control should be returned ->something_bad_has_happened=true;continue;}}if(something_bad_has_happened) { // The things below will not be executedcontinue;}
// Other things may happen here as well, but they will not be executed//  once control is returned from the inner cycle.}

这里!所以,虽然简单的中断不起作用,但可以使用continue使其工作。

如果你只是简单地将逻辑从一种编程语言移植到Java,只是想让它工作,你可以尝试使用标签

breakcontinuelabel的演示:

Java关键字breakcontinue有一个默认值。它是“最近的循环”,今天,经过几年的使用Java,我刚刚得到了它!

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

import org.junit.Test;
/*** Created by cui on 17-5-4.*/
public class BranchLabel {@Testpublic void test() {System.out.println("testBreak");testBreak();
System.out.println("testBreakLabel");testBreakLabel();
System.out.println("testContinue");testContinue();System.out.println("testContinueLabel");testContinueLabel();}
/**testBreaka=0,b=0a=0,b=1a=1,b=0a=1,b=1a=2,b=0a=2,b=1a=3,b=0a=3,b=1a=4,b=0a=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);}}}
/**testContinuea=0,b=0a=0,b=1a=0,b=3a=0,b=4a=1,b=0a=1,b=1a=1,b=3a=1,b=4a=2,b=0a=2,b=1a=2,b=3a=2,b=4a=3,b=0a=3,b=1a=3,b=3a=3,b=4a=4,b=0a=4,b=1a=4,b=3a=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);}}}
/**testBreakLabela=0,b=0,c=0a=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);}}}}
/**testContinueLabela=0,b=0,c=0a=0,b=0,c=1a=1,b=0,c=0a=1,b=0,c=1a=2,b=0,c=0a=2,b=0,c=1a=3,b=0,c=0a=3,b=0,c=1a=4,b=0,c=0a=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);}}}}}

Java8#0解决方案:

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

您可以执行以下操作:

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

Java没有像C++中那样的goto功能。但是,goto仍然是Java中的保留关键字。他们将来可能会实现它。对于你的问题,答案是Java中有一个叫做标签的东西,你可以对其应用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");}

标记中断概念用于打破java中的嵌套循环,通过使用标记的出路,您可以在任何位置打破循环的嵌套。示例1:

loop1:for(int i= 0; i<6; i++){for(int j=0; j<5; j++){if(i==3)break loop1;}}

假设有3个循环,你想终止循环3:示例2:

loop3:for(int i= 0; i<6; i++){loop2:for(int k= 0; k<6; k++){loop1:for(int j=0; j<5; j++){if(i==3)break loop3;}}}

下面是一个示例,每当满足条件时,“关掉”语句将光标推出for循环。

public class Practice3_FindDuplicateNumber {
public static void main(String[] args) {Integer[] inp = { 2, 3, 4, 3, 3 };Integer[] aux_arr = new Integer[inp.length];boolean isduplicate = false;for (int i = 0; i < aux_arr.length; i++) {
aux_arr[i] = -1;
}outer: for (int i = 0; i < inp.length; i++) {if (aux_arr[inp[i]] == -200) {System.out.println("Duplicate Found at index: " + i + " Carrying value: " + inp[i]);isduplicate = true;break outer;} else {aux_arr[inp[i]] = -200;}}
for (Integer integer : aux_arr) {System.out.println(integer);}
if (isduplicate == false) {System.out.println("No Duplicates!!!!!");} else {System.out.println("Duplicates!!!!!");}}
}

Demo

public static void main(String[] args) {outer:while (true) {while (true) {break outer;}}}

它很容易使用label,您可以使用标签从内部循环中打破外部循环,考虑下面的示例,

public class Breaking{public static void main(String[] args) {outerscope:for (int i=0; i < 5; i++) {for (int j=0; j < 5; j++) {if (condition) {break outerscope;}}}}}

另一种方法是使用中断变量/标志来跟踪所需的中断。考虑以下示例。

public class Breaking{public static void main(String[] args) {boolean isBreaking = false;for (int i=0; i < 5; i++) {for (int j=0; j < 5; j++) {if (condition) {isBreaking = true;break;}}if(isBreaking){break;}}}}

我更喜欢使用第一种方法。

当您需要从多个循环中退出时,单独使用'down'关键字不是合适的方法。您可以退出立即循环不管你的语句有多少个循环。您可以使用“打破”与标签!这里我使用了标签“abc”您可以在Java中的任何函数中编写如下代码

这段代码展示了如何从最外循环退出

 abc:for (int i = 0; i < 10; i++) {for (int j = 0; j < 10; j++) {for (int k = 0; k < 10; k++) {if (k == 1){break abc;}}}}

您还可以使用关掉语句退出嵌套循环中的任何循环。

    for (int i = 0; i < 10; i++) {abc:for (int j = 0; j < 10; j++) {for (int k = 0; k < 10; k++) {if (k == 1){break abc;}}}}

下面的代码显示了从最内层循环退出的示例。在其他工作中,执行以下代码后,您处于“k”变量循环的外部,仍然处于“j”和“i”变量循环的内部。

    for (int i = 0; i < 10; i++) {for (int j = 0; j < 10; j++) {for (int k = 0; k < 10; k++) {if (k == 1){break;}}}}

如果有人正在寻找添加标记循环的Kotlin方法

loop@ for (i in 1..100) {for (j in 1..100) {if (...) break@loop}}

来源