etc./StackOverFlow

Java에서 중첩 루프에서 벗어나려면 어떻게 해야 합니까?

청렴결백한 만능 재주꾼 2021. 12. 26. 04:07
반응형

질문자 :boutta


다음과 같은 중첩 루프 구조가 있습니다.

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

이제 어떻게 두 루프에서 벗어날 수 있습니까? 비슷한 질문을 살펴보았지만 특별히 Java와 관련된 질문은 없습니다. 대부분의 goto를 사용했기 때문에 이러한 솔루션을 적용할 수 없었습니다.

내부 루프를 다른 방법으로 사용하고 싶지 않습니다.

루프를 다시 실행하고 싶지 않습니다. 깨면 루프 블록의 실행이 끝났습니다.



다른 답변자와 마찬가지로 루프를 다른 방법에 넣는 것을 선호 합니다. 이 경우 반복을 완전히 중지하기 위해 돌아갈 수 있습니다. 이 답변은 질문의 요구 사항을 충족하는 방법을 보여줍니다.

외부 루프에 대한 레이블과 함께 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

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

Zo72

루프 주위에 명명된 블록을 사용할 수 있습니다.

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

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

Elle Mundy

레이블을 사용할 수 있습니다.

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

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

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

Miguel Ping

breakgoto 가 마음에 들지 않으면 추가 중단 조건과 함께 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; } } }

zord

비슷한 작업을 수행해야 했지만 향상된 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; } } }

Swifty McSwifterton

루프 테스트에 명시적인 "종료"를 추가하는 것을 선호합니다. 루프가 일찍 종료될 수 있음을 일반 독자에게 분명히 합니다.

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

ddyer

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

Igor Rybak

레이블이 지정된 중단 개념은 Java에서 중첩 루프를 분리하는 데 사용됩니다. 레이블이 있는 중단 을 사용하면 모든 위치에서 루프의 중첩을 중단할 수 있습니다. 예 1:

 loop1: for(int i= 0; i<6; i++){ for(int j=0; j<5; j++){ if(i==3) break loop1; } }

3개의 루프가 있고 루프3을 종료하려고 한다고 가정합니다. 예 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; } } }

Bishal Jaiswal

일반적으로 이러한 경우에는 더 의미 있는 논리의 범위에 있게 됩니다. 문제의 반복된 '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배 더 많은 라인
  • 컴퓨팅 사이클의 더 많은 소비, 즉 알고리즘 관점에서 더 느립니다.
  • 더 많은 타이핑 작업

장점:

  • 기능적 세분성으로 인해 관심사 분리 비율이 더 높음
  • 재사용성 및 검색/조작 로직 제어의 높은 비율
  • 방법은 길지 않으므로 더 간결하고 이해하기 쉽습니다.
  • 높은 가독성 비율

따라서 다른 접근 방식을 통해 케이스를 처리하는 것뿐입니다.

기본적으로 이 질문의 저자에 대한 질문: 이 접근 방식에 대해 어떻게 생각하십니까?


Oleksii Kyslytsyn

label: 및 플래그를 사용하지 않고 모든 루프에서 중단할 수 있습니다.

그것은 단지 까다로운 솔루션입니다.

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

Hitendra Solanki

레이블을 사용합니다.

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

이 기사를 참조하십시오


Rumesh Eranga Hapuarachchi

가장 쉽고 간편한 방법..

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

Keshav bansal

데모

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

shellhub

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

Panzercrisis

그것이 어떤 함수 안에 있다면 왜 그것을 반환하지 않습니까?

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

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

user2875404

예 없이 언급된 또 다른 솔루션입니다(실제로 제품 코드에서 작동함).

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

ursa

break , continuelabel 데모:

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

Bill

for (int j = 0; j < 5; j++) //inner loop for (int j = 0; j < 5 && !exitloops; j++) 로 대체되어야 합니다.

True 이면 완전한 중첩 루프가 종료되어야 합니다. 그러나 우리가 상위 loop exitloops

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

그런 다음 이 내부 루프가 종료되도록 알리는 추가 플래그가 없기 때문에 내부 루프가 계속됩니다.

예: i = 3 이고 j=2 이면 조건은 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); } }

Vikrant Kashyap

둘 이상의 루프를 종료해야 하는 경우 'break' 키워드만 사용하는 것은 적절한 방법이 아닙니다. 명령문이 얼마나 많은 루프로 둘러싸여 있는지에 상관없이 즉시 루프에서 나갈 수 있습니다. 레이블과 함께 'break'를 사용할 수 있습니다! 여기에서 "abc"라는 레이블을 사용했습니다. Java의 모든 기능 내에서 다음과 같이 코드를 작성할 수 있습니다.

이 코드는 가장 바깥쪽 루프를 종료하는 방법을 보여줍니다.

 abc: for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { for (int k = 0; k < 10; k++) { if (k == 1){ break abc; } } } }

또한 break 문을 사용하여 중첩 루프의 모든 루프에서 나갈 수 있습니다.

 for (int i = 0; i < 10; i++) { abc:for (int j = 0; j < 10; j++) { for (int k = 0; k < 10; k++) { if (k == 1){ break abc; } } } }

다음 코드는 가장 안쪽 루프를 종료하는 예를 보여줍니다. 다른 작업에서는 다음 코드를 실행한 후 'k' 변수 루프 외부에 있고 여전히 'j' 및 'i' 변수 루프 내부에 있습니다.

 for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { for (int k = 0; k < 10; k++) { if (k == 1){ break; } } } }

RusJ

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

mtyson

Java에는 C++에서와 같이 goto 기능이 없습니다. 그러나 여전히 goto 는 Java에서 예약된 키워드입니다. 그들은 미래에 그것을 구현할 수 있습니다. continuebreak 문을 적용할 수 있는 레이블이라는 것이 있다는 것입니다. 아래 코드를 찾으십시오.

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

Harsh Vardhan

새로운 구현인 경우 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 사용하여 작동하도록 만들 수 있습니다.

단순히 하나의 프로그래밍 언어에서 Java로 논리를 이식하고 작업을 수행하려는 경우 레이블을 사용해 볼 수 있습니다.


Ravindra HV

label 을 사용하는 것은 상당히 쉽습니다. 레이블을 사용하여 내부 루프에서 외부 루프를 분리할 수 있습니다. 아래 예를 고려하세요.

 public class Breaking{ public static void main(String[] args) { outerscope: for (int i=0; i < 5; i++) { for (int j=0; j < 5; j++) { if (condition) { break outerscope; } } } } }

또 다른 접근 방식은 중단 변수/플래그를 사용하여 필요한 중단을 추적하는 것입니다. 다음 예를 고려하십시오.

 public class Breaking{ public static void main(String[] args) { boolean isBreaking = false; for (int i=0; i < 5; i++) { for (int j=0; j < 5; j++) { if (condition) { isBreaking = true; break; } } if(isBreaking){ break; } } } }

그러나 첫 번째 방법을 사용하는 것이 좋습니다.


Kiran Maniya

내부 루프를 깨기 위해 레이블을 사용하기만 하면 됩니다.

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

Mahesh Peri

다음을 수행할 수 있습니다.

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

Siddharth Choudhary

출처 : http:www.stackoverflow.com/questions/886955/how-do-i-break-out-of-nested-loops-in-java

반응형