tutorial - while loop java




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

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

我有這樣的嵌套循環結構:

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

也許有一個功能?

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

你只是使用標籤來打破內部循環

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

你可以做一件事

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

那麼,對我來說這似乎是一個簡單的方法。



另一個解決方案,沒有例子提到(它實際上在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];
    }
}

如果你不喜歡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;
        }
    }
}

對於某些情況,我們可以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;
  }

從技術上講,正確的答案是標記外部循環。 在實踐中,如果你想在內部循環中的任何一點退出,那麼你最好將代碼外部化成一個方法(如果需要的話,是一個靜態方法),然後調用它。

這將為可讀性帶來回報。

代碼會變成這樣的:

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

您可以在不使用任何標籤和標誌的情況下從所有循環中斷開。

這只是一個棘手的解決方案。

這裡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