programing

Java 8의 체인 옵션

sourcejob 2022. 12. 13. 20:06
반응형

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);
}

두 가지 방법 중 하나를 사용하여 첫 번째 스트림을 옵션으로 변환하려면

  1. find Any() 또는 find First()
  2. 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

반응형