IT박스

Java에서 선택 사항 또는 기타 선택 사항

itboxs 2020. 7. 6. 08:06
반응형

Java에서 선택 사항 또는 기타 선택 사항


Java 8 의 새로운 Optional 유형 으로 작업하고 있으며 기능적으로 지원되지 않는 일반적인 작업 인 "orElseOptional"과 같은 기능을 살펴 보았습니다.

다음 패턴을 고려하십시오.

Optional<Result> resultFromServiceA = serviceA(args);
if (resultFromServiceA.isPresent) return result;
else {
    Optional<Result> resultFromServiceB = serviceB(args);
    if (resultFromServiceB.isPresent) return resultFromServiceB;
    else return serviceC(args);
}

이 패턴에는 여러 형태가 있지만, 현재 옵션이 존재하지 않는 경우에만 호출되는 새로운 옵션을 생성하는 함수를 취하는 옵션에 대해 "orElse"를 원합니다.

구현은 다음과 같습니다.

public Optional<T> orElse(Supplier<Optional<? extends T>> otherSupplier) {
    return value != null ? this : other.get();
}

의도하지 않은 방식으로 Optional을 사용하는 경우와 같은 방법이 존재하지 않는 이유가 있는지, 사람들 이이 사건을 처리하기 위해 다른 방법을 생각해 낸 경우 궁금합니다.

내 코드로 작업하는 사람들이 반드시 존재한다는 것을 알지 못하기 때문에 사용자 정의 유틸리티 클래스 / 메소드와 관련된 솔루션은 우아하지 않다고 생각해야합니다.

또한 누구나 아는 경우 그러한 방법이 JDK 9에 포함됩니까? 어떻게 그러한 방법을 제안 할 수 있습니까? 이것은 나에게 API에 대한 눈부신 누락처럼 보입니다.


이 형태의 JDK (9)의 일부입니다 or걸립니다 Supplier<Optional<T>>. 그러면 귀하의 예는 다음과 같습니다.

return serviceA(args)
    .or(() -> serviceB(args))
    .or(() -> serviceC(args));

자세한 내용은 내가 작성한 Javadoc 또는 이 게시물을 참조하십시오 .


현재 API를 고려한 가장 깨끗한 "시도 서비스"접근 방식은 다음과 같습니다.

Optional<Result> o = Stream.<Supplier<Optional<Result>>>of(
    ()->serviceA(args), 
    ()->serviceB(args), 
    ()->serviceC(args), 
    ()->serviceD(args))
.map(Supplier::get)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();

중요한 측면은 한 번 작성해야하는 (일정한) 작업 체인이 아니라 다른 서비스를 추가하는 것이 얼마나 쉬운 지 (또는 서비스 목록을 수정하는 것이 일반적 임)입니다. 여기에서 싱글을 추가하거나 제거하는 ()->serviceX(args)것으로 충분합니다.

스트림의 지연 평가로 인해 선행 서비스가 비어 있지 않은 것을 리턴하면 서비스가 호출되지 않습니다 Optional.


예쁘지는 않지만 작동합니다.

return serviceA(args)
  .map(Optional::of).orElseGet(() -> serviceB(args))
  .map(Optional::of).orElseGet(() -> serviceC(args))
  .map(Optional::of).orElseGet(() -> serviceD(args));

.map(func).orElseGet(sup)와 함께 사용하기에 매우 편리한 패턴입니다 Optional. "이것이 Optional가치를 포함 한다면 v, 나에게 func(v), 그렇지 않으면 나에게주세요 sup.get()"를 의미합니다.

이 경우에 우리는를 호출하고을 serviceA(args)얻는다 Optional<Result>. Optional포함되어 있으면 vget Optional.of(v)을 원하지만 비어 있으면 얻을 수 serviceB(args)있습니다. 더 많은 대안으로 헹구십시오.

이 패턴의 다른 용도는

  • .map(Stream::of).orElseGet(Stream::empty)
  • .map(Collections::singleton).orElseGet(Collections::emptySet)

Perhaps this is what you're after: Get value from one Optional or another

Otherwise, you may want to have a look at Optional.orElseGet. Here's an example of what I think that you're after:

result = Optional.ofNullable(serviceA().orElseGet(
                                 () -> serviceB().orElseGet(
                                     () -> serviceC().orElse(null))));

Assuming you're still on JDK8, there are several options.

Option#1: make your own helper method

E.g.:

public class Optionals {
    static <T> Optional<T> or(Supplier<Optional<T>>... optionals) {
        return Arrays.stream(optionals)
                .map(Supplier::get)
                .filter(Optional::isPresent)
                .findFirst()
                .orElseGet(Optional::empty);
    }
}

So that you could do:

return Optionals.or(
   ()-> serviceA(args),
   ()-> serviceB(args),
   ()-> serviceC(args),
   ()-> serviceD(args)
);

Option#2: use a library

E.g. google guava's Optional supports a proper or() operation (just like JDK9), e.g.:

return serviceA(args)
  .or(() -> serviceB(args))
  .or(() -> serviceC(args))
  .or(() -> serviceD(args));

(Where each of the services returns com.google.common.base.Optional, rather than java.util.Optional).


This is looks like a good fit for pattern matching and a more traditional Option interface with Some and None implementations (such as those in Javaslang, FunctionalJava) or a lazy Maybe implementation in cyclops-react.I'm the author of this library.

With cyclops-react you can also use structural pattern matching on JDK types. For Optional you can match on the present and absent cases via the visitor pattern. it would look something like this -

  import static com.aol.cyclops.Matchables.optional;

  optional(serviceA(args)).visit(some -> some , 
                                 () -> optional(serviceB(args)).visit(some -> some,
                                                                      () -> serviceC(args)));

참고URL : https://stackoverflow.com/questions/28818506/optional-orelse-optional-in-java

반응형