Java 8의 체인 옵션
최초로 존재하는 옵션을 반환할 수 있도록 옵션을 체인화하는 방법을 찾고 있습니다.존재하지 않는 경우Optional.empty()반환해야 합니다.
다음과 같은 방법이 몇 가지 있다고 가정합니다.
Optional<String> find1()
쇠사슬을 묶으려고 합니다.
Optional<String> result = find1().orElse( this::find2 ).orElse( this::find3 );
하지만 물론 그것은 효과가 없다. 왜냐하면orElse값을 기대하고 있습니다.orElseGet기대하다Supplier.
스트림 사용:
Stream.of(find1(), find2(), find3())
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
검색 방법을 쉽게 평가할 필요가 있는 경우 공급업체 기능을 사용하십시오.
Stream.of(this::find1, this::find2, this::find3)
.map(Supplier::get)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
Sauli의 대답에 영감을 받아, 그것을 사용할 수 있다.flatMap()방법.
Stream.of(this::find1, this::find2, this::find3)
.map(Supplier::get)
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
.findFirst();
Optional을 Stream으로 변환하는 것은 번거로운 작업입니다.이것은 JDK9로 수정될 것 같습니다.그래서 이렇게 쓸 수 있어요.
Stream.of(this::find1, this::find2, this::find3)
.map(Supplier::get)
.flatMap(Optional::stream)
.findFirst();
Java 9 출시 후 업데이트
원래 Java 8에 대한 질문이었지만 Java 9에서 소개되었습니다.이것으로 다음과 같이 문제를 해결할 수 있었다.
Optional<String> result = find1()
.or(this::find2)
.or(this::find3);
다음과 같이 할 수 있습니다.
Optional<String> resultOpt = Optional.of(find1()
.orElseGet(() -> find2()
.orElseGet(() -> find3()
.orElseThrow(() -> new WhatEverException()))));
IMO의 가독성이 향상되는지는 잘 모르겠습니다만, Guava는 옵션 체인의 방법을 제공하고 있습니다.
import com.google.common.base.Optional;
Optional<String> resultOpt = s.find1().or(s.find2()).or(s.find3());
다른 방법으로 문제를 해결할 수 있지만 JDK의 표준 Optional 클래스는 사용하지 않습니다.
표준 API를 유지하려면 다음과 같은 간단한 유틸리티 메서드를 작성할 수 있습니다.
static <T> Optional<T> or(Optional<T> first, Optional<T> second) {
return first.isPresent() ? first : second;
}
그 후:
Optional<String> resultOpt = or(s.find1(), or(s.find2(), s.find3()));
체인(chain)에 대한 옵션이 많은 경우 이미 언급한 대로 Stream 접근 방식을 사용하는 것이 좋습니다.
Java 9 이후
독자들이 (오늘) 찾고 있는 가장 유력한 경우
result = find1()
.or(this::find2)
.or(this::find3);
자바 8
result = Optional.ofNullable(find1()
.orElse(find2()
.orElse(find3()
.orElse(null))));
Alexis C의 답변에 근거하지만, 이 질문에 대한 보금자리는 없습니다.orElses
String result = find1()
.map(Optional::of)
.orElseGet(Foo::find2())
.map(Optional::of)
.orElseGet(Foo::find3())
.orElseThrow(() -> new WhatEverException())
를 삭제합니다.orElseThrow당신이 원한다면Optional<String>그 결과입니다.
요령은 에 의해 반환되는 각 옵션을 랩하는 것입니다.findX각각 앞에 있는 다른 선택사항으로orElseGet.
// Java 9+
find1().or(() -> find2()).or(() -> find3());
// Java 8
Optional.ofNullable(
find1().orElse(
find2().orElse(
find3().orElse( null )
)));
캐스케이드 체인에 사용할 수 있습니다. ifPresentOrElse
find1().ifPresentOrElse( System.out::println, new Runnable() {
public void run() {
find2().ifPresentOrElse( System.out::println, new Runnable() {
public void run() {
find3().ifPresentOrElse( System.out::println, new Runnable() {
public void run() {
System.err.println( "nothing found…" );
}
} );
}
} );
}
} );
가치 있는 일을 하다Optional교환이 필요했습니다.System.out::println당신의 것과 함께Consumer
(이 솔루션에서는 다른 소비자도 가능합니다.)
이러한 모든 문제에 대한 일반적인 솔루션:
public static <T> T firstMatch(final Predicate<T> matcher, final T orElse, final T... values) {
for (T t : values) {
if (matcher.test(t)) {
return t;
}
}
return orElse;
}
다음 작업을 수행할 수 있습니다.
public static <T> Optional<T> firstPresent(final Optional<T>... values) {
return firstMatch(Optional::isPresent, Optional.empty(), values);
}
두 가지 방법 중 하나를 사용하여 첫 번째 스트림을 옵션으로 변환하려면
- find Any() 또는 find First()
- min() / max()
옵션을 가져오면 옵션에는 스트림클래스와 map()에도 존재하는2개의 인스턴스 메서드가 추가됩니다.메서드 및 출력 사용을 확인하려면 ifPresent(시스템)에서 사용합니다.출력: Println)
예:
스트림 s = 스트림.of(1,2,3,4);
s.find First().filter(a)-> a+1). if Present(시스템).출력: Println)
출력: 2
아마도 하나일 것이다.
public <T> Optional<? extends T> firstOf(Optional<? extends T> first, @SuppressWarnings("unchecked") Supplier<Optional<? extends T>>... supp) {
if (first.isPresent()) return first;
for (Supplier<Optional <? extends T>> sup : supp) {
Optional<? extends T> opt = sup.get();
if (opt.isPresent()) {
return opt;
}
}
return Optional.empty();
}
public <T> Optional<? extends T> firstOf(Optional<? extends T> first, Stream<Supplier<Optional<? extends T>>> supp) {
if (first.isPresent()) return first;
Stream<Optional<? extends T>> present = supp.map(Supplier::get).filter(Optional::isPresent);
return present.findFirst().orElseGet(Optional::empty);
}
할 거다.
첫 번째는 여러 공급업체에서 반복됩니다. 번째가 있지 않은 Optional<>이 반환됩니다.수 없는 에는 빈 을 돌려드립니다.Optional.
도 같은 .StreamSuppliers그 을 요구 나서, 그 있는 「경고」 「경고」 「경고」 「경고」(경고」 「경고) 「경고」 「경고」에 대해서, 「경고」 「경고」Optional 있지 않은 첫 번째 빈 빈이 반환됩니다. 비어 있지 않은 첫 번째 항목이 반환됩니다.빈 항목이 없는 경우 빈 항목이 반환됩니다.
언급URL : https://stackoverflow.com/questions/28514704/chaining-optionals-in-java-8
'programing' 카테고리의 다른 글
| "-"(마이너스 기호)가 처음 나올 때 문자열을 PHP를 사용하여 $vars 두 개로 분할하려면 어떻게 해야 합니까? (0) | 2022.12.13 |
|---|---|
| MySQL 행을 읽기 전용으로 설정하는 방법이 있습니까? (0) | 2022.12.13 |
| 일치하는 행을 삭제하는 더 빠른 방법 (0) | 2022.12.13 |
| 반복기의 개수/길이/사이즈를 얻는 가장 좋은 방법은 무엇입니까? (0) | 2022.12.13 |
| 간단한 CLI Java linter가 있나요? (0) | 2022.12.13 |