A diferença entre map () e flatMap ()

A diferença entre map () e flatMap ()

*1. Visão geral *

As APIs map () _ e _flatMap () _ decorrem de linguagens funcionais. No Java 8, você pode encontrá-los em _Optional, Stream e em CompletableFuture (embora com nome ligeiramente diferente).

Streams representam uma sequência de objetos, enquanto opcionais são classes que representam um valor que pode estar presente ou ausente. Entre outras operações agregadas, temos os métodos _map () _ e _flatMap () _.

Apesar de ambos terem os mesmos tipos de retorno , , são bem diferentes. Vamos explicar essas diferenças analisando alguns exemplos de fluxos e opcionais.

Leitura adicional:

https://www..com/java-iterate-map [Iterar sobre um mapa em Java]

Aprenda maneiras diferentes de iterar através das entradas de um mapa em Java.

https://www..com/jackson-map [Mapear serialização e desserialização com Jackson]

Um guia rápido e prático para serializar e desserializar o Java Maps usando Jackson.

https://www..com/java-map-duplicate-keys [Como armazenar chaves duplicadas em um mapa em Java?]

Um guia rápido e prático para lidar com chaves duplicadas usando multimaps em Java.

===* 2. Mapa e Flatmap em Opcionais *

O método map () _ funciona bem com _Optional - se a função retornar o tipo exato que precisamos:

Optional<String> s = Optional.of("test");
assertEquals(Optional.of("TEST"), s.map(String::toUpperCase));

No entanto, em casos mais complexos, podemos receber uma função que retorna um Optional também. Nesses casos, o uso de _map () _ levaria a uma estrutura aninhada, pois a implementação _map () _ realiza um empacotamento adicional internamente.

Vamos ver outro exemplo para entender melhor essa situação:

assertEquals(Optional.of(Optional.of("STRING")),
  Optional
  .of("string")
  .map(s -> Optional.of("STRING")));

Como podemos ver, terminamos com a estrutura aninhada Optional <Optional <>> . Embora funcione, é bastante complicado de usar e não fornece segurança nula adicional, portanto, é melhor manter uma estrutura plana.

É exatamente isso que _flatMap () _ nos ajuda a fazer:

assertEquals(Optional.of("STRING"), Optional
  .of("string")
  .flatMap(s -> Optional.of("STRING")));

===* 3. Mapa e Flatmap no Streams *

Ambos os métodos funcionam da mesma maneira para Optional.

O método map () _ agrupa a sequência subjacente em uma instância _Stream, enquanto o método _flatMap () _ permite evitar a estrutura _Stream <Stream <R>> _ aninhada.

No exemplo a seguir, map () _ produz um _Stream que consiste nos resultados da aplicação do método _toUpperCase () _ aos elementos da entrada _Stream: _

List<String> myList = Stream.of("a", "b")
  .map(String::toUpperCase)
  .collect(Collectors.toList());
assertEquals(asList("A", "B"), myList);

_map () _ funciona muito bem em um caso tão simples, mas e se tivermos algo mais complexo, como uma lista de listas como entrada.

Vamos ver como isso funciona:

List<List<String>> list = Arrays.asList(
  Arrays.asList("a"),
  Arrays.asList("b"));
System.out.println(list);

Este trecho imprime uma lista de listas _ [[a], [b]] ._ + Agora, vamos usar um _flatMap () _:

System.out.println(list
  .stream()
  .flatMap(Collection::stream)
  .collect(Collectors.toList()));
*O resultado desse snippet será achatado para _ [a, b] ._*

T o método flatMap () _ primeiro nivela a entrada _Stream de Streams para um Stream de Strings (para obter mais informações sobre achatamento, consulte o link:/java-flatten-nested-collections [article]). Posteriormente, funciona de maneira semelhante ao método _map () _.

4. Conclusão

O Java 8 nos dá a oportunidade de usar os métodos _map () _ e _flatMap () _ que originalmente eram usados ​​em linguagens funcionais.

Podemos invocá-los em Streams e Optionals. Esses métodos nos ajudam a obter objetos mapeados aplicando a função de mapeamento fornecida.

Como sempre, você pode conferir os exemplos fornecidos neste artigo over no GitHub.