Estratégia com flatMap

Criar um Stream a partir de List:

Stream products = payments.stream()
.map(Payment::getProducts)
.flatMap(p -> p.stream());

Alternativa com method reference:

.flatMap(List::stream)

Forma ainda mais enxuta:

Stream products = payments.stream()
.flatMap(p -> p.getProducts().stream());

Observações:

  • Não há diferença significativa de performance entre as abordagens.

  • A escolha deve priorizar a legibilidade do código.

Contando quantas vezes cada produto foi vendido

Gerar Map com a contagem de cada produto:

Map topProducts = payments.stream()
.flatMap(p -> p.getProducts().stream())
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

Impressão do Map:

  • Print padrão pode gerar uma linha longa e difícil de ler:

System.out.println(topProducts);

  • Melhor: imprimir cada entrada em linha separada:

topProducts.entrySet().stream()
.forEach(System.out::println);

Observação: Encadear o entrySet().stream() logo após o collect() impede o uso posterior do Map.

Encontrando o produto mais vendido

Usar max com Comparator baseado no valor:

topProducts.entrySet().stream()
.max(Comparator.comparing(Map.Entry::getValue))
.ifPresent(System.out::println);

  • max(...) retorna um Optional>

  • Por isso, o uso de .ifPresent(...)

Exemplo: PagamentosProdutosMaisVendidosExemplo.java