Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

[Projeto] Desafios

Olá!

Seguem minhas resoluções:

package br.com.alura.exercicios;

import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {

        //1 - Dada a lista de números inteiros a seguir, encontre o maior número dela.

        List<Integer> numeros = Arrays.asList(10, 20, 30, 40, 50);
        numeros.stream()
                .sorted()
                .toList()
                .reversed()
                .stream()
                .limit(1)
                .forEach(System.out::println);

// 2 -Dada a lista de palavras (strings) abaixo, agrupe-as pelo seu tamanho.
// No código a seguir, há um exemplo prático do resultado esperado.

        List<String> palavras = Arrays.asList("java", "stream", "lambda", "code");
       Map <Integer, List<String>> grupoPalavras =  palavras.stream()
                       .collect(Collectors.groupingBy(String::length));
        System.out.println(grupoPalavras);

        //3 - Dada a lista de nomes abaixo, concatene-os separados por vírgula.
        // No código a seguir, há um exemplo prático do resultado esperado.

        List<String> nomes = Arrays.asList("Alice", "Bob", "Charlie");

        String nomesConcatenados = nomes.stream()
                .collect(Collectors.joining(", "));

        System.out.println(nomesConcatenados);

        //4 - Dada a lista de números inteiros abaixo,
        // calcule a soma dos quadrados dos números pares.

        List<Integer> numerosQuadrados = Arrays.asList(1, 2, 3, 4, 5, 6);

       int somaQuadrados =  numerosQuadrados.stream()
                .filter(q -> q % 2 == 0)
                .map(q -> q * q)
                .reduce(0,(totaL, numero) -> totaL + numero);

        System.out.println(somaQuadrados);

        //5 - Dada uma lista de números inteiros, separe os números pares dos ímpares.

        List<Integer> numerosSeparar = Arrays.asList(1, 2, 3, 4, 5, 6);

       Map<Boolean, List<Integer>> listasSeparadas =  numerosSeparar.stream()
                .collect(Collectors.groupingBy(s -> s % 2 == 0));

       List<Integer> pares = listasSeparadas.get(true);
       List<Integer> impares = listasSeparadas.get(false);

        System.out.println("Lista de números pares: " + pares);
        System.out.println("Lista de números ímpares: " + impares);

List<Produto> produtos = Arrays.asList(
            new Produto("Smartphone", 800.0, "Eletrônicos"),
            new Produto("Notebook", 1500.0, "Eletrônicos"),
            new Produto("Teclado", 200.0, "Eletrônicos"),
            new Produto("Cadeira", 300.0, "Móveis"),
            new Produto("Monitor", 900.0, "Eletrônicos"),
            new Produto("Mesa", 700.0, "Móveis")
        );

//6 - Dada a lista de produtos acima, agrupe-os por categoria em um Map<String, List<Produto>>.
Map<String, List<Produto>> agrupadoCategoria = produtos.stream()
        .collect(Collectors.groupingBy(Produto::getCategoria));

        System.out.println(agrupadoCategoria);

        //7 - Dada a lista de produtos acima,
        // conte quantos produtos há em cada categoria e armazene em um Map<String, Long>.

        Map<String, Long> contagemProdutos = produtos.stream()
                .collect(Collectors.groupingBy(Produto::getCategoria,
                        Collectors.counting()));

        System.out.println(contagemProdutos);

//8 - Dada a lista de produtos acima, encontre o produto mais caro de cada categoria e armazene o resultado em um Map<String,
// Optional<Produto>>.

        Map<String, Optional<Produto>> produtoMaisCaro = produtos.stream()
                .collect(Collectors.groupingBy(Produto::getCategoria,
                        Collectors.maxBy(Comparator.comparingDouble(Produto::getPreco))));

        System.out.println(produtoMaisCaro);

//9 - Dada a lista de produtos acima, calcule o total dos preços dos produtos em cada categoria e armazene o resultado em um Map<String, Double>.
        Map<String, Double> somaValores = produtos.stream()
                .collect(Collectors.groupingBy(Produto::getCategoria,
                        Collectors.reducing(0.0,Produto::getPreco,Double::sum)));

        System.out.println(somaValores);


         }
}
2 respostas
solução!

Olá, Victor! Tudo bem?

Parabéns pela excelente resolução dos exercícios! Você demonstrou um domínio sólido sobre a API de Streams e os Collectors do Java 8+, que são fundamentais para escrever um código limpo e funcional no ecossistema Spring.

Aqui estão alguns destaques técnicos da sua implementação:

Análise das Resoluções

  • Agrupamento e Estatísticas: Nos exercícios 6 ao 9, você utilizou com maestria o Collectors.groupingBy. A forma como você combinou o agrupamento com outros coletores, como counting(), maxBy() e reducing(), mostra que você compreendeu o conceito de Downstream Collectors.
  • Manipulação de Strings: O uso do Collectors.joining(", ") no exercício 3 é a forma mais eficiente e legível de concatenar elementos em Java moderno.
  • Lógica de Particionamento: No exercício 5, você usou o groupingBy com um predicado booleano. Uma alternativa interessante para esse caso específico seria o Collectors.partitioningBy(s -> s % 2 == 0), que é otimizado justamente para divisões binárias (true/false).

Dica de Refatoração (Clean Code)

No Exercício 1, você utilizou uma estratégia criativa de ordenar, reverter e limitar a lista para achar o maior valor. Embora funcione, o Java oferece uma forma mais direta e performática:

Optional<Integer> maior = numeros.stream().max(Comparator.naturalOrder());

Isso evita o custo computacional de ordenar toda a lista ($O(n \log n)$) quando você só precisa encontrar o valor máximo ($O(n)$).


O Próximo Passo: Lambdas e Spring

Como você está no curso de Spring Framework, lembre-se de que essa fluidez com Streams será essencial para manipular dados vindos do banco através do Spring Data JPA. Muitas vezes, transformamos as entidades que vêm do banco em DTOs (Data Transfer Objects) usando exatamente essas cadeias de map e collect.

Victor, excelente trabalho nos 100 posts e na dedicação com o Java! No exercício 8, você notou que o resultado é um Optional<Produto>? Como você faria para exibir apenas o nome do produto mais caro, tratando o caso de a lista estar vazia?

Olá, Evandro!

Obrigado, tem sido uma jornada de muito aprendizado. Pensando na sua proposta bvolei o seguinte resultado:

import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {

        //8 - Dada a lista de produtos acima, encontre o produto mais caro de cada categoria e armazene o resultado em um Map<String,
// Optional<Produto>>.
        List<Produto> produtos = Arrays.asList(
                new Produto("Smartphone", 800.0, "Eletrônicos"),
                new Produto("Notebook", 1500.0, "Eletrônicos"),
                new Produto("Teclado", 200.0, "Eletrônicos"),
                new Produto("Cadeira", 300.0, "Móveis"),
                new Produto("Monitor", 900.0, "Eletrônicos"),
                new Produto("Mesa", 700.0, "Móveis")
        );

        Map<String, Optional<Produto>> produtoMaisCaro = produtos
                .stream()
                .filter(produto -> produtos != null && produto.getCategoria() != null)
                .collect( Collectors.groupingBy(Produto::getCategoria,
                        Collectors.maxBy(Comparator.comparingDouble(Produto::getPreco))));

        produtoMaisCaro.forEach((categoria, optProd) -> {
            String nome = optProd.map(Produto::getNome).orElse("Sem produtos");
            System.out.println("Categoria: " + categoria + "| Produto mais caro: " + nome);
        });




    }

}