Java 9のオプションのAPIの追加

Java 9のオプションのAPIの追加

1. 概要

この記事では、Optional APIへのJava 9の追加について説明します。

モジュール性に加えて、Java 9はOptionalクラスに3つの非常に便利なメソッドも追加しています。

2. or()メソッド

Optionalが空の場合、Optional.を返す他のアクションを実行したい場合があります。

以前のJava9では、OptionalクラスにはorElse()メソッドとorElseGet()メソッドしかありませんでしたが、どちらもラップされていない値を返す必要があります。

Java 9では、Optionalが空の場合に別のOptionalを遅延的に返すor()メソッドが導入されています。 最初のOptionalに定義された値がある場合、or()メソッドに渡されたラムダは呼び出されず、値は計算されず、返されません。

@Test
public void givenOptional_whenPresent_thenShouldTakeAValueFromIt() {
    //given
    String expected = "properValue";
    Optional value = Optional.of(expected);
    Optional defaultValue = Optional.of("default");

    //when
    Optional result = value.or(() -> defaultValue);

    //then
    assertThat(result.get()).isEqualTo(expected);
}

Optional beingが空の場合、返されるresultdefaultValue:と同じになります

@Test
public void givenOptional_whenEmpty_thenShouldTakeAValueFromOr() {
    // given
    String defaultString = "default";
    Optional value = Optional.empty();
    Optional defaultValue = Optional.of(defaultString);

    // when
    Optional result = value.or(() -> defaultValue);

    // then
    assertThat(result.get()).isEqualTo(defaultString);
}

3. ifPresentOrElse()メソッド

Optionalインスタンスがある場合、その基になる値に対して特定のアクションを実行したいことがよくあります。 一方、Optionalemptyの場合は、ログに記録するか、メトリックをインクリメントしてその事実を追跡します。

ifPresentOrElse()メソッドは、そのようなシナリオのために正確に作成されます。 Optionalが定義されている場合に呼び出されるConsumerと、Optionalが空の場合に実行されるRunnableを渡すことができます。

Optionalが定義されており、値が存在する場合は特定のカウンターをインクリメントするとします。

@Test
public void givenOptional_whenPresent_thenShouldExecuteProperCallback() {
    // given
    Optional value = Optional.of("properValue");
    AtomicInteger successCounter = new AtomicInteger(0);
    AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);

    // when
    value.ifPresentOrElse(
      v -> successCounter.incrementAndGet(),
      onEmptyOptionalCounter::incrementAndGet);

    // then
    assertThat(successCounter.get()).isEqualTo(1);
    assertThat(onEmptyOptionalCounter.get()).isEqualTo(0);
}

2番目の引数として渡されたコールバックが実行されなかったことに、注意してください。

空のOptional,の場合、2番目のコールバックが実行されます。

@Test
public void givenOptional_whenNotPresent_thenShouldExecuteProperCallback() {
    // given
    Optional value = Optional.empty();
    AtomicInteger successCounter = new AtomicInteger(0);
    AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);

    // when
    value.ifPresentOrElse(
      v -> successCounter.incrementAndGet(),
      onEmptyOptionalCounter::incrementAndGet);

    // then
    assertThat(successCounter.get()).isEqualTo(0);
    assertThat(onEmptyOptionalCounter.get()).isEqualTo(1);
}

4. stream()メソッド

Java 9のOptionalクラスに追加される最後のメソッドは、stream()メソッドです。

Javaには、コレクションを操作でき、多くの関数型プログラミングの概念を利用できる、非常に流暢でエレガントなStreamAPIがあります。 最新のJavaバージョンでは、allows us to treat the Optional instance as a Stream.クラスにstream()メソッドが導入されています。

定義されたOptionalがあり、その上でstream()メソッドを呼び出しているとしましょう。 これにより、1つの要素のStreamが作成され、Stream API:で使用可能なすべてのメソッドを使用できます。

@Test
public void givenOptionalOfSome_whenToStream_thenShouldTreatItAsOneElementStream() {
    // given
    Optional value = Optional.of("a");

    // when
    List collect = value.stream().map(String::toUpperCase).collect(Collectors.toList());

    // then
    assertThat(collect).hasSameElementsAs(List.of("A"));
}

一方、Optionalが存在しない場合は、stream()メソッドを呼び出すと、空のStream:が作成されます。

@Test
public void givenOptionalOfNone_whenToStream_thenShouldTreatItAsZeroElementStream() {
    // given
    Optional value = Optional.empty();

    // when
    List collect = value.stream()
      .map(String::toUpperCase)
      .collect(Collectors.toList());

    // then
    assertThat(collect).isEmpty();
}

Streams of Optionals.をすばやくフィルタリングできるようになりました

空のStreamを操作しても効果はありませんが、stream()メソッドのおかげで、Optional APIをStreamAPIとチェーンできるようになりました。 これにより、よりエレガントで流fluentなコードを作成できます。

5. 結論

この簡単な記事では、Java 9OptionalのAPIの追加について説明しました。

ソースOptionalが空の場合に、or()メソッドを使用してオプションを返す方法を確認しました。 値が存在する場合はifPresentOrElse()を使用してConsumerを実行し、存在しない場合は別のコールバックを実行しました。

最後に、stream()メソッドを使用してOptionalStreamAPIでチェーンする方法を確認しました。

これらすべての例とコードスニペットの実装は、GitHub projectにあります。これはMavenプロジェクトであるため、そのままインポートして実行するのは簡単です。