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á.