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. Solução com flatMap: Stream linhas = Files.list(Paths.get("./caminho/do/diretório")) .filter(p -> p.toString().endsWith(".java")) .flatMap(p -> lines(p)); // Converte Stream → Stream Resultado: Todas as linhas de todos os arquivos .java em um único Stream. 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) 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 usuarios = new HashSet(); public void add(Usuario u) { usuarios.add(u); } public Stream getUsuarios() { return usuarios.stream(); } } Lista de grupos: List grupos = Arrays.asList(englishSpeakers, spanishSpeakers); Problema: grupos.stream().map(g -> g.getUsuarios()) gera Stream>. Solução com flatMap: grupos.stream() .flatMap(g -> g.getUsuarios()) // Achata para Stream .distinct() // Remove usuários duplicados .forEach(System.out::println); 5. Exemplo com Pedidos de Usuários Contexto: Cada Usuario possui uma lista de Pedido: class Usuario { private List pedidos; public Stream getPedidos() { return pedidos.stream(); } } Objetivo: Obter todos os pedidos de uma lista de usuários. Código: List usuarios = ...; Stream todosPedidos = usuarios.stream() .flatMap(u -> u.getPedidos()); // Converte Stream → Stream 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.

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.
Solução com flatMap:
Stream linhas = Files.list(Paths.get("./caminho/do/diretório"))
.filter(p -> p.toString().endsWith(".java"))
.flatMap(p -> lines(p)); // Converte Stream> → Stream
Resultado: Todas as linhas de todos os arquivos .java em um único Stream.
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)
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 usuarios = new HashSet<>();
public void add(Usuario u) { usuarios.add(u); }
public Stream getUsuarios() { return usuarios.stream(); }
}
Lista de grupos:
List grupos = Arrays.asList(englishSpeakers, spanishSpeakers);
Problema:
grupos.stream().map(g -> g.getUsuarios()) gera Stream>.
Solução com flatMap:
grupos.stream()
.flatMap(g -> g.getUsuarios()) // Achata para Stream
.distinct() // Remove usuários duplicados
.forEach(System.out::println);
5. Exemplo com Pedidos de Usuários
Contexto:
Cada Usuario possui uma lista de Pedido:
class Usuario {
private List pedidos;
public Stream getPedidos() { return pedidos.stream(); }
}
Objetivo: Obter todos os pedidos de uma lista de usuários.
Código:
List usuarios = ...;
Stream todosPedidos = usuarios.stream()
.flatMap(u -> u.getPedidos()); // Converte Stream> → Stream
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.