提问



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


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


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


我不想把内循环放在另一种方法中。


更新:我不想重新运行循环,当我完成循环块的执行时。

最佳参考


像其他的回答者一样,我肯定更喜欢将内循环放在一个不同的方法中。这个答案只是说明了如何满足问题中的要求。


您可以将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

其它参考1


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


这样可以获得可读性。


代码会变成这样的:


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

其它参考2


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


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

其它参考3


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


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

其它参考4


你可以使用标签:


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

其它参考5


也许有功能?


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

其它参考6


您可以使用临时变量:


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

其它参考7


如果你不喜欢breakgoto s,你可以使用传统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;
        }
    }
}

其它参考8


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

其它参考9


我更喜欢在循环测试中添加一个明确的退出。它清楚地说明了
任何随意的读者,循环可能提前终止。


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

其它参考10


Java 8 Stream解决方案:[69]


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**/);

其它参考11


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


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


这里条件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");
    }
}

其它参考12


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


通常这种情况属于更有意义的逻辑范围,让我们说一些搜索或操纵一些迭代的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;
}


主要缺点:



  • 大约两次行

  • 更多的计算周期消耗,意味着它从算法的角度来看更慢

  • 更多打字工作



专业人士:



  • 由于功能粒度而导致的关注点分离率更高

  • 更高的可用性和控制率
    在没有
  • 的情况下搜索/操纵逻辑
  • 方法不长,因此它们更紧凑,更容易理解

  • 主观上更高的可读性比率



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


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

其它参考13


最好的方法..


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

其它参考14


如果它在某个功能内部,为什么不回复它:


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

其它参考15


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


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

其它参考16


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

其它参考17


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



  如果它是一个新的实现,你可以尝试重写逻辑
  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并且只是想让事情正常工作,您可以尝试使用标签

其它参考18


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

}

其它参考19


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


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



  示例:if 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);
    }
}

其它参考20


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

其它参考21


使用标签。


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


参考这篇文章[72]

其它参考22


另一个解决方案,没有示例提及(它实际上在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];
    }
}

其它参考23


您可以执行以下操作:



  1. 将局部变量设置为false

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

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


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


其它参考24


对于某些情况,我们可以在这里有效地使用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;
}

其它参考25


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


喜欢这个 :


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

其它参考26


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


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

其它参考27


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

其它参考28


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


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

其它参考29


通过检查内部循环的变量,检查内部循环是否通过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   
     } 
}