Adições opcionais à API do Java 9

Adições opcionais à API do Java 9

1. Visão geral

Neste artigo, veremos as adições do Java 9 à APIOptional.

Além da modularidade, o Java 9 também está adicionando três métodos muito úteis para a classeOptional.

2. O Métodoor()

Às vezes, quando nossoOptional está vazio, queremos executar alguma outra ação que também retorna um Optional.

Antes do Java 9, a classeOptional tinha apenas os métodosorElse()eorElseGet(), mas ambos precisam retornar valores não agrupados.

Java 9 introduz o métodoor() que retorna outroOptional preguiçosamente se nossoOptional estiver vazio. Se nosso primeiroOptional tiver um valor definido, o lambda passado para o métodoor() não será chamado e o valor não será calculado e retornado:

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

No caso deOptional being vazio, oresult retornado será o mesmo que odefaultValue:

@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. O MétodoifPresentOrElse()

Quando temos uma instânciaOptional, geralmente queremos executar uma ação específica sobre o valor subjacente dela. Por outro lado, seOptional forempty, queremos registrá-lo ou rastrear esse fato incrementando alguma métrica.

O métodoifPresentOrElse() é criado exatamente para tais cenários. Podemos passarConsumer que será invocado seOptional estiver definido eRunnable que será executado seOptional estiver vazio.

Digamos que temos umOptional definido e queremos incrementar um contador específico se o valor estiver presente:

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

Observe que o retorno de chamada passado como o segundo argumento não foi executado.

No caso de umOptional, vazio, o segundo retorno de chamada é executado:

@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. O Métodostream()

O último método, que é adicionado à classeOptional no Java 9, é o métodostream().

Java tem uma APIStream muito fluente e elegante que pode operar nas coleções e utiliza muitos conceitos de programação funcional. A versão mais recente do Java introduz o métodostream() na classeOptional queallows us to treat the Optional instance as a Stream.

Digamos que temos umOptional definido e estamos chamando o métodostream() nele. Isso criará umStream de um elemento no qual podemos usar todos os métodos que estão disponíveis naStream 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"));
}

Por outro lado, seOptional não estiver presente, chamar o métodostream() nele criará umStream: vazio

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

Agora podemos filtrar rapidamenteStreams of Optionals.

Operar noStream vazio não terá nenhum efeito, mas graças ao métodostream(), agora podemos encadear a APIOptional com a APIStream. Isso nos permite criar um código mais elegante e fluente.

5. Conclusão

Neste artigo rápido, vimos as adições de API do Java 9Optional.

Vimos como usar o métodoor() para retornar um opcional caso a fonteOptional esteja vazia. UsamosifPresentOrElse() para executarConsumer se o valor estiver presente e, caso contrário, execute outro callback.

Finalmente, vimos como encadearOptional com a APIStream usando o métodostream().

A implementação de todos esses exemplos e trechos de código pode ser encontrada emGitHub project - este é um projeto Maven, portanto, deve ser fácil de importar e executar como está.