web-dev-qa-db-ja.com

Javaで入れ子になったループから抜け出す方法は?

私はこのようなネストしたループ構成を持っています:

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

では、どうすれば両方のループから抜け出すことができますか?私は似たような質問を見ましたが、特にJavaに関するものはありません。私はこれらの解決策を適用することができませんでした。

内側のループを別の方法で入れたくありません。

ループを再実行したくありません。壊れたらループブロックの実行は終了です。

1675
boutta

他の回答者と同様に、私は間違いなく 好み ループを別の方法にすることを望みます。その時点であなたは完全に反復を止めるために戻ることができます。この答えは、質問の要件をどのように満たすことができるかを示しているだけです。

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
2201
Jon Skeet

技術的に正しい答えは、外側のループにラベルを付けることです。実際には、内側のループ内の任意の場所で終了したい場合は、コードをメソッド(必要に応じて静的メソッド)に外部化してから呼び出すほうがよいでしょう。

それは読みやすさの見返りとなります。 

コードは次のようになります。 

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

ループの周りに名前付きブロックを使うことができます。

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

ラベルは使いません。入るのは悪い習慣のようです。これが私のやり方です。

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;
        }
    }
}
120
Elle Mundy

ラベルを使うことができます:

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

関数を使う:

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

あなたは一時的な変数を使うことができます:

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;
         }
    }
}
16
Miguel Ping

breaksとgotosが気に入らない場合は、for-inの代わりに "伝統的な" forループを使用して、追加の中止条件を指定できます。

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

私は同様のことをする必要がありました、しかし私はそれをするためにenhanced 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;
        }
    }
}
10

私はループテストに明示的な "exit"を追加することを好みます。それはループが早く終了するかもしれないことをどんなカジュアルな読者にも明らかにします。

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

Java 8 Stream solution:

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

Label:やflagsを使わずに、すべてのループから抜け出すことができます。

それはトリッキーな解決策です。

ここで、condition1はループKとJから抜け出すために使用される条件です。[condition] 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");
    }
}
5
Hitendra Hckr

通常そのような場合、それはより意味のあるロジックの範囲に入ってきます。問題の反復された '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;
}

主な短所

  • およそ2倍の行
  • 計算サイクルの消費量が増えるため、アルゴリズム的な観点からは遅くなります。
  • もっとタイピング作業

長所:

  • 機能的な細分性のために、関心事の分離に対する比率が高い
  • 再利用性と検索/操作ロジックの制御の高い比率
  • 手法は長くはないので、よりコンパクトで理解しやすい
  • 主観的に読みやすさの割合

そのため、別の方法でケースを処理するだけです。

基本的にこの質問の作者に対する質問です。あなたはこのアプローチについてどう思いますか?

5

最も簡単で簡単な方法.

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;
     }
}
3
Keshav bansal

もしそれが何らかの関数の中にあるなら、なぜあなたはただそれを返さないでください: 

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

どちらかというと珍しいアプローチですが、コード長の点では( パフォーマンスではなく )、これが最も簡単な方法です。

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

ラベルを使用してください。

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

この記事を参照してください

3
Rumesh Eranga

例を挙げずに述べたもう1つの解決策(実際には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は内部的、私的、そしてno-stack-traceで加速されるべきです。

private static class BreakLoopException extends Exception {
    @Override
    public StackTraceElement[] getStackTrace() {
        return new StackTraceElement[0];
    }
}
3
ursa

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

for (int j = 0; j < 5; j++) //inner loopfor (int j = 0; j < 5 && !exitloops; j++)に置き換えてください。

ここで、この場合、conditionがTrueであれば、完全なネストループは終了するはずです。しかし、もし私達がexitloopsを上限のloopに対してのみ使用するならば 

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

この内部ループに終了を通知する追加のフラグがないため、内部ループは続行します。 

例:i = 3およびj=2の場合、conditionはfalseです。しかし、内側のループj=3の次の繰り返しでは、条件(i*j)9になります。これはtrueですが、j5になるまで内側のループは続きます。

そのため、内側のループにも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);
    }
}
2
Vikrant Kashyap

@ 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;
        }
    }
}
2
mtyson
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;
    }
}
2
Panzercrisis

もしそれが新しい実装であれば、ロジックを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を使用して機能させることができます。

単純に1つのプログラミング言語からJavaにロジックを移植していて、うまく機能させたい場合は labels を使用してみてください。

2
Ravindra HV

ラベル付きブレーク という概念は、Javaでネストしたループを分割するために使用されます。ラベル付きブレークを使用すると、ループのネストを任意の位置で分割できます。例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;
        }
    }
}
1
Bishal Jaiswal

デモ

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

次のことができます。

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

場合によっては、ここで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;
}
1
Dharmik Patel

外側のループのためのフラグを作成し、内側のループが実行されるたびにそれをチェックすることでさえも、答えになり得ます。

このような:

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

内部ループの変数をチェックして、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   
     } 
}
0
Edd

内側のループを壊すためにラベルを使用します

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
Mahesh P

以下は、条件が満たされたときに "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!!!!!");
        }
    }

}
0
Deb

JavaにはC++のようなgoto機能はありません。それでも、gotoはJavaの予約キーワードです。彼らは将来それを実装するかもしれません。あなたの質問に対して、答えはあなたがcontinuebreakステートメントを適用できるJavaのラベルと呼ばれるものがあるということです。以下のコードを見つけてください。

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");
}
0
Harsh Vardhan
boolean condition = false;
for (Type type : types) {
    for (int i = 0; i < otherTypes.size && !condition; i ++) {
        condition = true; // If your condition is satisfied
    }
}

処理が終了したときのフラグとしてconditionを使用してください。その後、内側のループは条件が満たされていない間だけ継続します。どちらの方法でも、外側のループはchugginを続けます。

0
astryk