私はこのようなネストしたループ構成を持っています:
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
技術的に正しい答えは、外側のループにラベルを付けることです。実際には、内側のループ内の任意の場所で終了したい場合は、コードをメソッド(必要に応じて静的メソッド)に外部化してから呼び出すほうがよいでしょう。
それは読みやすさの見返りとなります。
コードは次のようになります。
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);
}
}
}
}
ループの周りに名前付きブロックを使うことができます。
search: {
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break search;
}
}
}
}
ラベルは使いません。入るのは悪い習慣のようです。これが私のやり方です。
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;
}
}
}
ラベルを使うことができます:
label1:
for (int i = 0;;) {
for (int g = 0;;) {
break label1;
}
}
関数を使う:
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;
}
}
}
}
あなたは一時的な変数を使うことができます:
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;
}
}
}
break
sとgoto
sが気に入らない場合は、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;
}
}
}
私は同様のことをする必要がありました、しかし私はそれをするために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;
}
}
}
私はループテストに明示的な "exit"を追加することを好みます。それはループが早く終了するかもしれないことをどんなカジュアルな読者にも明らかにします。
boolean earlyExit = false;
for(int i = 0 ; i < 10 && !earlyExit; i++) {
for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; }
}
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**/);
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");
}
}
通常そのような場合、それはより意味のあるロジックの範囲に入ってきます。問題の反復された '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;
}
主な短所
長所:
そのため、別の方法でケースを処理するだけです。
基本的にこの質問の作者に対する質問です。あなたはこのアプローチについてどう思いますか?
最も簡単で簡単な方法.
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) {
for (Type t : types2) {
if (some condition) {
return value;
}
}
}
どちらかというと珍しいアプローチですが、コード長の点では( パフォーマンスではなく )、これが最も簡単な方法です。
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
}
}
ラベルを使用してください。
INNER:for(int j = 0; j < numbers.length; j++) {
System.out.println("Even number: " + i + ", break from INNER label");
break INNER;
}
例を挙げずに述べたもう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];
}
}
break
、continue
、およびlabel
のデモ:
Javaキーワードbreak
とcontinue
にはデフォルト値があります。それは「最も近いループ」であり、そして今日、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);
}
}
}
}
}
for (int j = 0; j < 5; j++) //inner loop
は for (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
ですが、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);
}
}
@ 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;
}
}
}
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;
}
}
もしそれが新しい実装であれば、ロジックを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 を使用してみてください。
ラベル付きブレーク という概念は、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;
}
}
}
デモ
public static void main(String[] args) {
outer:
while (true) {
while (true) {
break outer;
}
}
}
次のことができます。
ローカル変数をfalse
に設定します
中断したいときは、最初のループでその変数true
を設定してください。
次に、外側のループをチェックインして、条件が設定されているかどうかを外側のループからも判断することができます。
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;
}
外側のループのためのフラグを作成し、内側のループが実行されるたびにそれをチェックすることでさえも、答えになり得ます。
このような:
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;
}
内部ループの変数をチェックして、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
}
}
内側のループを壊すためにラベルを使用します
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");
}
}
以下は、条件が満たされたときに "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!!!!!");
}
}
}
JavaにはC++のようなgoto機能はありません。それでも、goto
はJavaの予約キーワードです。彼らは将来それを実装するかもしれません。あなたの質問に対して、答えはあなたがcontinue
とbreak
ステートメントを適用できる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");
}
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を続けます。