1975

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

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

现在我怎样才能打破这两个循环?我看过类似的问题,但没有一个特别关注 Java。我无法应用这些解决方案,因为大多数使用 goto。

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

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

4

36 回答 36

2618

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

您可以将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
于 2009-05-20T09:11:22.983 回答
424

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

这将为可读性带来回报。

代码会变成这样:

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);
            }
        }
    }
}
于 2011-11-14T18:26:53.423 回答
230

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

search: {
    for (Type type : types) {
        for (Type t : types2) {
            if (some condition) {
                // Do something and break...
                break search;
            }
        }
    }
}
于 2009-05-20T09:12:12.450 回答
150

我从不使用标签。进入这似乎是一种不好的做法。这是我要做的:

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;
        }
    }
}
于 2011-12-07T17:52:26.387 回答
120

您可以使用标签:

label1: 
for (int i = 0;;) {
    for (int g = 0;;) {
      break label1;
    }
}
于 2009-05-20T09:11:56.663 回答
44

使用一个函数:

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;
      }
    }
  }
}
于 2009-05-20T11:43:00.307 回答
24

您可以使用临时变量:

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;
         }
    }
}
于 2009-05-20T09:11:59.127 回答
17

如果你不喜欢breaks 和gotos,你可以使用“传统”的 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;
        }
    }
}
于 2013-12-21T22:56:34.260 回答
13

我需要做类似的事情,但我选择不使用增强的 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;
        }
    }
}
于 2012-02-05T06:04:30.153 回答
11

我更喜欢在循环测试中添加一个明确的“退出”。它使任何不经意的读者都清楚循环可能会提前终止。

boolean earlyExit = false;
for(int i = 0 ; i < 10 && !earlyExit; i++) {
     for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; }
}
于 2014-08-04T17:29:32.277 回答
11

当您需要退出多个循环时,单独使用“break”关键字不是合适的方法。无论您的语句被多少个循环包围,您都可以退出立即循环。您可以使用带有标签的“break”!在这里,我使用了标签“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;
              } 
        } 
    } 
}

您也可以使用 break 语句退出嵌套循环中的任何循环。

    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;
              } 
        } 
    } 
}
于 2020-10-17T09:02:59.137 回答
10

Java 8Stream解决方案:

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**/);
于 2017-07-16T10:24:26.957 回答
9

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

public Object searching(Object[] types) { // Or manipulating
    List<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;
}

主要缺点:

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

优点:

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

因此,它只是通过不同的方法处理此案。

基本上是向这个问题的作者提出的一个问题:您如何看待这种方法?

于 2016-01-28T18:53:55.333 回答
9

带标签的break概念用于打破Java中的嵌套循环,通过使用带标签的break,您可以在任何位置打破循环的嵌套。示例 1:

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

假设有 3 个循环并且您想要终止 loop3: 示例 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;
        }
    }
}
于 2019-04-04T10:15:17.207 回答
8

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

这只是棘手的解决方案。

这里 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");
    }
}
于 2014-05-21T14:33:06.670 回答
7

使用标签。

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

参考这篇文章

于 2014-06-01T12:41:33.550 回答
6

最好最简单的方法..

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;
     }
}
于 2015-08-23T21:04:40.140 回答
6

演示

public static void main(String[] args) {
    outer:
    while (true) {
        while (true) {
            break outer;
        }
    }
}
于 2019-08-26T12:11:33.187 回答
5
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;
    }
}
于 2013-09-11T22:14:59.033 回答
5

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

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];
    }
}
于 2014-10-10T13:57:30.213 回答
5

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

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
    }
}
于 2015-04-25T22:01:06.530 回答
5

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

for (Type type : types) {
    for (Type t : types2) {
         if (some condition) {
            return value;
         }
    }
}
于 2016-08-25T11:25:58.363 回答
5

它相当容易使用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;
            }
        }
    }
}

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

于 2019-09-20T11:40:09.247 回答
4

breakcontinue和的演示label

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);
                }
            }
        }
    }
}
于 2017-05-04T07:41:13.620 回答
3

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

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

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

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

示例: ifi = 3j=2then 条件是false。但是在内部循环的下一次迭代中,j=3 条件(i*j)变为9istrue但内部循环将继续直到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);
    }
}
于 2016-04-08T04:29:58.523 回答
2

像@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;
        }
    }
}
于 2014-09-13T19:00:17.890 回答
2

如果是新实现,可以尝试将逻辑重写为 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) { // The things below will not be executed
        continue;
    }

    // Other things may happen here as well, but they will not be executed
    //  once control is returned from the inner cycle.
}

这里!因此,虽然简单的中断不起作用,但可以使用continue.

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

于 2017-04-01T19:54:07.760 回答
2

Java 没有 C++ 中的 goto 功能。但是,仍然goto是 Java 中的保留关键字。他们可能会在未来实施它。对于您的问题,答案是 Java 中有一种称为标签的东西,您可以对其应用continueandbreak语句。找到下面的代码:

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");
}
于 2018-08-04T11:38:35.613 回答
1

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

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");
}
}
于 2012-10-17T11:50:49.393 回答
1

甚至为外部循环创建一个标志并检查每次执行内部循环后是否可以作为答案。

像这样:

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;
}
于 2013-04-28T05:08:33.753 回答
1
boolean condition = false;
for (Type type : types) {
    for (int i = 0; i < otherTypes.size && !condition; i ++) {
        condition = true; // If your condition is satisfied
    }
}

用作condition完成处理时的标志。然后内部循环仅在未满足条件时继续。无论哪种方式,外循环都会继续运行。

于 2014-07-11T16:46:28.197 回答
1

在某些情况下,我们可以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;
}
于 2017-03-24T01:43:41.713 回答
1

您可以执行以下操作:

  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
        }
    }
    
于 2017-09-19T05:41:51.633 回答
1

下面是一个示例,只要满足条件,“break”语句就会将光标推出 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!!!!!");
        }
    }

}
于 2019-05-08T10:20:32.597 回答
0

通过检查内部循环的变量,检查是否使用 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   
     } 
}
于 2013-05-07T18:57:20.207 回答
-10

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

相反,在内部循环中抛出异常,并用 try catch 块for封装两个循环。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.
  }

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

于 2016-03-31T18:33:14.557 回答