java - while - loops中文




在Java中打破嵌套循环 (20)

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

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

现在我怎么能摆脱两个循环。 我看过类似的问题,但没有一个关于Java的具体问题。 由于大多数使用gotos,我无法应用这些解决方案。

我不想将内部循环置于不同的方法中。

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


Java 8 Stream解决方案:

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

(编辑:和其他答案一样,我肯定更喜欢把内部循环放在一个不同的方法中,这个答案只是说明了如何满足问题的要求。)

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

也许有一个功能?

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

你可以做一件事

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

那么,对我来说这似乎是一个简单的方法。


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

另一个解决方案,没有例子提到(它实际上在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.
}

当然,打破例外应该是内部的,私人的,并且使用无堆栈跟踪加速:

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

对于某些情况,我们可以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;
  }

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

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

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

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

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

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

如果它是一个新的实现,你可以尝试重写逻辑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中,而只是想让这件事情起作用,您可以尝试使用labels


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

boolean earlyExit = false;
for(int i=0;i<10&&!earlyExit; i++) {
 for(int j=0;i<10&&!earlyExit; j++) { earlyExit=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;
        }
    }
}

最简单的方法..

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

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

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

长期以来,我一直在想为这类问题分享这种类型的答案。

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

主要缺点:

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

优点:

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

所以它只是通过一种不同的方式来处理案件。

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


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




loops