Java 8 스트림을 중단하거나 각 스트림에서 반환하시겠습니까?
외부 반복을 사용하는 경우Iterable
사용하고 있다break
또는return
각 루프에 대해 다음과 같이 확장됩니다.
for (SomeObject obj : someObjects) {
if (some_condition_met) {
break; // or return obj
}
}
어떻게 하면break
또는return
Java 8 lamda 식에서 내부 반복을 사용합니다.
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);
람다의 반환은 각각에 대한 연속값이지만 중단에 해당하는 값은 없습니다.돌아가기만 하면 계속할 수 있습니다.
someObjects.forEach(obj -> {
if (some_condition_met) {
return;
}
})
이것은 다음 경우에 가능합니다.Iterable.forEach()
(단, 신뢰할 수 있는 것은 아닙니다).Stream.forEach()
). 해결책은 좋지 않지만 가능합니다.
경고: 비즈니스 로직을 제어하는 데 사용할 수 없습니다.단, 비즈니스 로직을 실행하는 동안 발생하는 예외적인 상황을 처리하는 데만 사용해야 합니다.forEach()
자원 접근이 갑자기 정지되는 등 처리된 오브젝트 중 하나가 계약을 위반하고 있습니다(예를 들어 스트림의 모든 요소가 계약을 위반해서는 안 된다고 계약서에 기재되어 있습니다).null
갑자기 그 중 하나가null
) 등입니다.
의 매뉴얼에 따르면:
각 요소에 대해 지정된 액션을 수행합니다.
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
}
아래는 제가 프로젝트에서 사용한 솔루션을 찾으십시오.대신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>
일반적인 할 수 (「」를 사용하는 것).T
되는 ★★★bool
는를 더 - )을 씁니다.Predicate<T>
이상적이지 않아요
9에서 Java 9+로 takeWhile
:
MutableBoolean ongoing = MutableBoolean.of(true);
someobjects.stream()...takeWhile(t -> ongoing.value()).forEach(t -> {
// doing something.
if (...) { // want to break;
ongoing.setFalse();
}
});
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();
그러나 안정적인 결과를 원할 경우 대신 find First()를 사용합니다.
또한 일치하는 패턴(anyMatch()/allMatch)은 부울만 반환하며 일치하는 오브젝트는 얻을 수 없습니다.
나는 이런 일을 통해 성취했다
private void doSomething() {
List<Action> actions = actionRepository.findAll();
boolean actionHasFormFields = actions.stream().anyMatch(actionHasMyFieldsPredicate());
if (actionHasFormFields){
context.addError(someError);
}
}
}
private Predicate<Action> actionHasMyFieldsPredicate(){
return action -> action.getMyField1() != null;
}
이를 수행하려면 peek(..)와 anyMatch(..)를 조합합니다.
예를 들어 다음과 같습니다.
someObjects.stream().peek(obj -> {
<your code here>
}).anyMatch(obj -> !<some_condition_met>);
또는 일반적인 util 메서드를 작성합니다.
public static <T> void streamWhile(Stream<T> stream, Predicate<? super T> predicate, Consumer<? super T> consumer) {
stream.peek(consumer).anyMatch(predicate.negate());
}
그리고 이렇게 쓰세요.
streamWhile(someObjects.stream(), obj -> <some_condition_met>, obj -> {
<your code here>
});
public static void main(String[] args) {
List<String> list = Arrays.asList("one", "two", "three", "seven", "nine");
AtomicBoolean yes = new AtomicBoolean(true);
list.stream().takeWhile(value -> yes.get()).forEach(value -> {
System.out.println("prior cond" + value);
if (value.equals("two")) {
System.out.println(value);
yes.set(false);
}
});
//System.out.println("Hello World");
}
이건 어때?
final BooleanWrapper condition = new BooleanWrapper();
someObjects.forEach(obj -> {
if (condition.ok()) {
// YOUR CODE to control
condition.stop();
}
});
서 ★★★★★BooleanWrapper
는 플로우를 제어하기 위해 구현해야 하는 클래스입니다.
int valueToMatch = 7;
Stream.of(1,2,3,4,5,6,7,8).anyMatch(val->{
boolean isMatch = val == valueToMatch;
if(isMatch) {
/*Do whatever you want...*/
System.out.println(val);
}
return isMatch;
});
일치하는 부분만 작동하고 일치하는 부분을 찾은 후에는 반복이 중지됩니다.
anyMatch 사용을 권장합니다.예:-
return someObjects.stream().anyMatch(obj ->
some_condition_met;
);
anyMatch 에 대해서는, 다음의 투고를 참조해 주세요.- https://beginnersbook.com/2017/11/java-8-stream-anymatch-example/
언급URL : https://stackoverflow.com/questions/23308193/break-or-return-from-java-8-stream-foreach
'source' 카테고리의 다른 글
Nuxt Auth Module - ID/사용자명으로 사용자를 취득하는 방법 (0) | 2022.08.08 |
---|---|
Java 시간 기반 맵/캐시(만료된 키 포함) (0) | 2022.08.08 |
Laravel Passport 및 클라이언트 자격 증명으로 자체 API를 사용하는 방법 (0) | 2022.08.08 |
Vuejs. 하위 구성 요소의 프로펠을 변환해도 경고가 트리거되지 않습니다.왜 그럴까 (0) | 2022.08.08 |
Ubuntu에 Java 7 설치 (0) | 2022.08.08 |