DEV Community

FUNDAMENTOS JAVA
FUNDAMENTOS JAVA

Posted on • Edited on

8.9 FlatMap

1. Introdução ao flatMap

  • Objetivo: "Achatar" (flatten) Streams aninhados em um único Stream (ex: Stream> → Stream).
  • Aplicação: Útil para processar coleções de coleções, arquivos com múltiplas linhas, ou estruturas hierárquicas.

2. Exemplo Prático com Arquivos

Problema:
Usar map com Files.lines gera um Stream>, não desejado.

Files.lines(Path) retorna um Stream < String>, ou seja, um fluxo de linhas do arquivo. Quando usamos map(Files::lines), cada Path se transforma em um Stream < String>, resultando em um Stream de Streams, ou seja, Stream < Stream < String>>.

Solução com flatMap:

Stream<String> linhas = Files.list(Paths.get("./caminho/do/diretório"))  
                             .filter(p -> p.toString().endsWith(".java"))  
                             .flatMap(p -> lines(p)); // Converte Stream<Stream<String>> → Stream<String>  
Enter fullscreen mode Exit fullscreen mode

Resultado: Todas as linhas de todos os arquivos .java em um único Stream.

Exemplo: ArquivosFlatMap.java

3. Exemplo com Caracteres (flatMapToInt)
Objetivo: Obter todos os caracteres (como int) de todas as linhas dos arquivos.

Código:

IntStream caracteres = Files.list(Paths.get("./caminho/do/diretório"))  
                            .filter(p -> p.toString().endsWith(".java"))  
                            .flatMap(p -> lines(p))  
                            .flatMapToInt(s -> s.chars()); // Converte String → IntStream (evita boxing)  
Enter fullscreen mode Exit fullscreen mode

Resultado: IntStream com todos os caracteres dos arquivos.

4. Exemplo com Grupos de Usuários

Contexto:
Classe Grupo com usuários:

class Grupo {  
    private Set<Usuario> usuarios = new HashSet<>();  
    public void add(Usuario u) { usuarios.add(u); }  
    public Stream<Usuario> getUsuarios() { return usuarios.stream(); }  
}  
Enter fullscreen mode Exit fullscreen mode

Lista de grupos:

List<Grupo> grupos = Arrays.asList(englishSpeakers, spanishSpeakers);  
Enter fullscreen mode Exit fullscreen mode

Problema:
grupos.stream().map(g -> g.getUsuarios()) gera Stream>.

Solução com flatMap:

grupos.stream()  
      .flatMap(g -> g.getUsuarios()) // Achata para Stream<Usuario>  
      .distinct() // Remove usuários duplicados  
      .forEach(System.out::println);  
Enter fullscreen mode Exit fullscreen mode

Exemplo: UsuarioGrupo.java

5. Exemplo com Pedidos de Usuários

Contexto:
Cada Usuario possui uma lista de Pedido:

class Usuario {  
    private List<Pedido> pedidos;  
    public Stream<Pedido> getPedidos() { return pedidos.stream(); }    
Enter fullscreen mode Exit fullscreen mode

Objetivo: Obter todos os pedidos de uma lista de usuários.
Código:

List<Usuario> usuarios = ...;  
Stream<Pedido> todosPedidos = usuarios.stream()  
                                      .flatMap(u -> u.getPedidos()); // Converte Stream<Stream<Pedido>> → Stream<Pedido>  
Enter fullscreen mode Exit fullscreen mode

Exemplo: UsuarioPedido.java

6. Considerações Finais

Diferença entre map e flatMap:

  • map: Transforma elementos em outros tipos (pode gerar streams aninhados).
  • flatMap: Combina múltiplos streams em um único stream.

Operações relacionadas:

  • flatMapToInt, flatMapToLong, flatMapToDouble para streams primitivos.
  • Cuidado: Usar operações de curto-circuito (ex: limit, findFirst) em streams potencialmente infinitos.

Top comments (0)