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 に答える
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 に答える
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;
}

主な短所:

  • 約2倍のライン
  • 計算サイクルの消費量が増えるため、アルゴリズムの観点からは遅くなります
  • タイピング作業が増える

長所:

  • 機能的な粒度による関心の分離の比率が高い
  • 再利用性と検索/操作ロジックの制御の比率が高くなります。
  • メソッドは長くないため、よりコンパクトで理解しやすい
  • より高い可読率

したがって、別のアプローチでケースを処理しているだけです。

基本的に、この質問の作成者への質問: このアプローチについてどう思いますか?

于 2016-01-28T18:53:55.333 に答える
8

label: および flags を使用せずに、すべてのループから抜け出すことができます。

それはちょうどトリッキーな解決策です。

ここで、条件 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");
    }
}
于 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 に答える
5

何らかの関数内にある場合は、それを返さないのはなぜですか:

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

例なしで言及された別の1つのソリューション(実際には製品コードで動作します)。

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 に答える
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

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

例: if i = 3and j=2then condition is 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);
    }
}
于 2016-04-08T04:29:58.523 に答える
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

内側のループを壊すためにラベルを使用するだけです

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
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 に答える
-10

ラベルを使用すると、コードが goto ステートメントのように見えます。これは単なる考えです。

代わりに、内側のループで例外をスローし、2 つのループを 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 に答える