[java] 각 Java 8 스트림에서 중단 또는 리턴?

사용시 외부 반복 오버 Iterable우리 사용 break또는 return피 각 루프에서와 같은 향상된 :

for (SomeObject obj : someObjects) {
   if (some_condition_met) {
      break; // or return obj
   }
}

Java 8 람다 식에서 내부 반복 을 사용 break하거나 어떻게 사용할 수 있습니까?return

someObjects.forEach(obj -> {
   //what to do here?
})



답변

이것이 필요한 경우을 사용하지 말고 forEach스트림에서 사용할 수있는 다른 방법 중 하나를 사용하십시오. 어느 것이 목표인지에 달려 있습니다.

예를 들어,이 루프의 목표가 술어와 일치하는 첫 번째 요소를 찾는 것입니다.

Optional<SomeObject> result =
    someObjects.stream().filter(obj -> some_condition_met).findFirst();

(참고 : 스트림이 느리게 평가되기 때문에 전체 콜렉션을 반복하지 않습니다. 조건과 일치하는 첫 번째 오브젝트에서 중지됩니다).

컬렉션에 조건이 맞는 요소가 있는지 알고 싶다면 다음을 사용할 수 있습니다 anyMatch.

boolean result = someObjects.stream().anyMatch(obj -> some_condition_met);


답변

이것은 이다 가능 Iterable.forEach()(그러나 신뢰성과 Stream.forEach()). 이 솔루션은 좋은 아니지만, 그것은 이다 가능합니다.

경고 : 비즈니스 로직을 제어하는 ​​데 사용하지 말고 순전히을 실행하는 동안 발생하는 예외 상황을 처리하는 데 사용해야합니다 forEach(). 리소스가 갑자기 액세스를 중지하는 등 처리 된 개체 중 하나가 계약을 위반하고 있습니다 (예 : 계약에 따르면 스트림의 모든 요소가 null갑자기 갑자기 예기치 않은 요소 중 하나가되어야 함 null).

에 대한 문서에 따르면 Iterable.forEach():

모든 요소가 처리되거나 조치에서 예외가 발생 Iterable 될 때까지 의 각 요소에 대해 지정된 조치를 수행합니다. 조치에 의해 발생한 예외는 호출자에게 중계됩니다.

따라서 내부 루프를 즉시 중단시키는 예외가 발생합니다.

코드는 다음과 같습니다. 나는 그것을 좋아한다고 말할 수는 없지만 작동합니다. 당신 BreakException은 확장하는 자신의 클래스 를 만듭니다 RuntimeException.

try {
    someObjects.forEach(obj -> {
        // some useful code here
        if(some_exceptional_condition_met) {
            throw new BreakException();
       }
    }
}
catch (BreakException e) {
    // here you know that your condition has been met at least once
}

(가) 것을 알 수 try...catch있습니다 하지 않고 주위 전체 주위의 람다 식,하지만 forEach()방법. 더 잘 보이게하려면 다음 코드를보다 명확하게 보여주는 코드를 참조하십시오.

Consumer<? super SomeObject> action = obj -> {
    // some useful code here
    if(some_exceptional_condition_met) {
        throw new BreakException();
    }
});

try {
    someObjects.forEach(action);
}
catch (BreakException e) {
    // here you know that your condition has been met at least once
}


답변

람다에서의 리턴은 for-each에서의 계속과 동일하지만 휴식과 동등한 것은 없습니다. 계속하려면 반품을 수행하면됩니다.

someObjects.forEach(obj -> {
   if (some_condition_met) {
      return;
   }
})


답변

아래에는 프로젝트에서 사용한 솔루션이 있습니다. 대신 다음 forEach을 사용하십시오 allMatch.

someObjects.allMatch(obj -> {
    return !some_condition_met;
});


답변

어느 쪽이든 당신은 (대신 휴식을 가지고 있도록) 계속할지 여부를 나타내는 술어를 사용하는 방법을 사용해야 하거나 물론, 아주 추악한 방법 – 당신은 예외를 던질 필요가있다.

따라서 다음 forEachConditional과 같은 방법을 작성할 수 있습니다 .

public static <T> void forEachConditional(Iterable<T> source,
                                          Predicate<T> action) {
    for (T item : source) {
        if (!action.test(item)) {
            break;
        }
    }
}

대신에 Predicate<T>, 일반적인 방법 (a T를 가져오고 리턴하는 것과 같은)을 사용하여 자신 만의 기능적 인터페이스를 정의하고 싶을 수 bool있지만 기대를보다 명확하게 나타내는 이름 Predicate<T>은 여기에 이상적이지 않습니다.


답변

java8 + rxjava를 사용할 수 있습니다 .

//import java.util.stream.IntStream;
//import rx.Observable;

    IntStream intStream  = IntStream.range(1,10000000);
    Observable.from(() -> intStream.iterator())
            .takeWhile(n -> n < 10)
            .forEach(n-> System.out.println(n));


답변

병렬 작업에서 최대 성능을 얻으 려면 findFirst ()와 유사한 findAny ()를 사용하십시오 .

Optional<SomeObject> result =
    someObjects.stream().filter(obj -> some_condition_met).findAny();

그러나 안정적인 결과를 원하면 findFirst ()를 대신 사용하십시오.

또한 일치하는 패턴 (anyMatch () / allMatch)은 부울 만 반환하며 일치하는 객체는 얻지 않습니다.