programing

Java에서 네스트된 루프를 해제하려면 어떻게 해야 하나요?

prostudy 2022. 7. 4. 22:12
반응형

Java에서 네스트된 루프를 해제하려면 어떻게 해야 하나요?

네스트 루프 구조는 다음과 같습니다.

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

어떻게 하면 양쪽 루프를 벗어날 수 있을까요?비슷한 질문들을 살펴봤지만 자바와 관련된 질문은 없습니다.대부분 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

기술적으로 정답은 외부 루프에 라벨을 붙이는 것입니다.실제로 내부 루프 내의 임의의 포인트에서 종료하는 경우는, 코드를 메서드(필요한 경우는 스태틱한 메서드)로 외부화한 후 호출하는 것이 좋습니다.

그것은 가독성에 대한 보상을 받을 것이다.

코드는 다음과 같습니다.

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 §goto "할 수 있으며, 추가 조건인 "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;
        }
    }
}

저도 비슷한 작업을 해야 하는데 확장 루프를 사용하지 않기로 했습니다.

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

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

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

복수의 루프를 종료할 필요가 있는 경우는, 「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;
              } 
        } 
    } 
}

Java 8 솔루션:

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

라벨이 붙은 브레이크 개념은 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;
        }
    }
}

일반적으로 이러한 경우, 문제의 반복된 '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;
}

주요 단점:

  • 약 두 줄 더
  • 컴퓨팅 사이클 소비량 증가, 즉 알고리즘 관점에서 볼 때 속도가 느려집니다.
  • 더 많은 타이핑 작업

장점:

  • 기능적 입도 때문에 우려의 분리에 대한 비율이 높다.
  • 없는 검색/조절 논리의 재추적 및 제어의 더 높은 비율
  • 방법은 길지 않기 때문에 더 콤팩트하고 이해하기 쉽다
  • 높은 가독성 비율

그래서 그것은 단지 다른 접근법으로 사건을 처리하고 있을 뿐이다.

기본적으로 이 질문의 작성자에게 질문합니다.이 접근방식에 대해 어떻게 생각하십니까?

label: 및 flags를 사용하지 않고 모든 루프에서 분리할 수 있습니다.

그냥 까다로운 해결책이야.

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

라벨을 사용합니다.

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

이 기사를 참조해 주세요.

최적의 간단한 방법..

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

데모

public static void main(String[] args) {
    outer:
    while (true) {
        while (true) {
            break outer;
        }
    }
}
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;
    }
}

만약 어떤 기능 안에 있다면 그냥 돌려보내는 게 어때요?

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

예를 들어 설명하지 않은 다른 하나의 솔루션(실제로는 Prod Code로 동작합니다).

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-module no-stack-module, no-stack-module(no-stack-module), no-stack-module(no-stack-module)을 해야 합니다.

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

to it it it it it it it it it it 。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;
            }
        }
    }
}

하지만 저는 첫 번째 방법을 사용하는 것을 선호합니다.

데모: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++).

이 경우 조건이 다음과 같은 경우 완전한 네스트된 루프가 종료됩니다.True하지만 만약 우리가exitloops상층부에만loop

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

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

자바에는 C++와 같은 goto 기능이 없습니다.하지만 여전히,goto는 Java에서 예약된 키워드입니다.그들은 장래에 그것을 실행할지도 모른다.당신의 질문에 대한 답변은 자바에 라벨이라는 것이 있다는 것입니다.continue그리고.break진술.아래에서 코드를 찾습니다.

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

새로운 구현의 경우 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로 로직을 포팅하고 동작시키기만 원한다면 라벨을 사용해 볼 수 있습니다.

내부 루프를 끊는 라벨만 사용하시면 됩니다.

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

언급URL : https://stackoverflow.com/questions/886955/how-do-i-break-out-of-nested-loops-in-java

반응형