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();
find 메서드를 느리게 평가해야하는 경우 공급자 함수를 사용하십시오.
Stream.of(this::find1, this::find2, this::find3)
.map(Supplier::get)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
다음과 같이 할 수 있습니다.
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()));
체인에 대한 선택 사항이 많으면 이미 언급 한 다른 방법과 같이 Stream 접근 방식을 사용하는 것이 좋습니다.
Sauli의 답변에서 영감을 받아이 flatMap()
방법 을 사용할 수 있습니다 .
Stream.of(this::find1, this::find2, this::find3)
.map(Supplier::get)
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
.findFirst();
옵션을 스트림으로 변환하는 것은 번거 롭습니다. 분명히 이것은 JDK9 로 수정 될 것 입니다. 그래서 이것은 다음과 같이 쓸 수 있습니다.
Stream.of(this::find1, this::find2, this::find3)
.map(Supplier::get)
.flatMap(Optional::stream)
.findFirst();
Java 9 출시 후 업데이트
원래 질문은 Java 8에 관한 것이었지만 Optional::or
Java 9에서 도입되었으므로 다음과 같이 문제를 해결할 수 있습니다.
Optional<String> result = find1()
.or(this::find2)
.or(this::find3);
선택적 체이닝 을 수행하려면 먼저 두 가지 방법 중 하나를 사용하여 Stream을 Optional 로 변환 합니다.
- findAny () 또는 findFirst ()
- 최소 최대()
Once optional is obtained optional has two more instance method which are also present in Stream class i.e filter and map(). use these on methods and to check output use ifPresent(System.out :: Println)
ex:
Stream s = Stream.of(1,2,3,4);
s.findFirst().filter((a)->a+1).ifPresent(System.out :: Println)
Output is : 2
Maybe one of
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);
}
will do.
The first one iterates over an array of suppliers. The first non-empty Optional<>
is returned. If we don't find one, we return an empty Optional
.
The second one does the same with a Stream
of Suppliers
which is traversed, each one asked (lazily) for their value, which is then filtered for empty Optional
s. The first non-empty one is returned, or if no such exists, an empty one.
ReferenceURL : https://stackoverflow.com/questions/28514704/chaining-optionals-in-java-8
'IT박스' 카테고리의 다른 글
원시 HTML 코드를 PRE 또는 이와 유사한 것으로 표시하는 방법 (0) | 2020.12.15 |
---|---|
신뢰할 수있는 인증서없이 .appx를 설치 하시겠습니까? (0) | 2020.12.15 |
보수가 printf를 통해 다르게 작동하는 이유는 무엇입니까? (0) | 2020.12.15 |
Windows에서 MBCS와 UTF-8의 차이점 (0) | 2020.12.15 |
절대 URL인지 상대 URL인지 확인 (0) | 2020.12.15 |