ganhando_produtividade_com_Stream_API_Java icon indicating copy to clipboard operation
ganhando_produtividade_com_Stream_API_Java copied to clipboard

Duvida desafio 7

Open thiagovanzele opened this issue 2 years ago • 9 comments

Boa tarde, prô!

Estou com dúvida no exercicio 7, como localizar o segundo maior valor da lista usando stream, qual seria a maneira correta usando stream? pensei em organizar do menor para o maior, contar a quantidade de elementos da stream e usar o skip para pular ate o penultimo, mas nao parece ser a maneira correta...

thiagovanzele avatar Aug 20 '23 18:08 thiagovanzele

int segundoMaior = numeros.stream().sorted().toList().get(11); Fiz desse jeito, na prática deu certo, mas como disse, não parece a maneira correta...

thiagovanzele avatar Aug 20 '23 18:08 thiagovanzele

System.out.println(nums.stream().distinct().sorted((a, b) -> b.compareTo(a)).skip(1).findFirst().orElse(null));

Fiz assim. Tive que usar um recurso de optional, mesmo não assistindo o vídeo sobre essa parte ainda. Mas acho que ficou mais dinâmico, visto que você pode adicionar números na lista depois e o código ainda assim retornar o resultado correto.

siqueirarxd avatar Aug 22 '23 11:08 siqueirarxd

Boa tarde, @thiagovanzele. Parabéns pelos estudos, viu? Está indo bem!

Deixa eu te mostrar uma forma de fazer. Lembrando que existem outras formas:

  1. Removemos elementos repetidos com distinct() para garantir que a lista tem apenas elementos únicos.
  2. Ordenamos os números na ordem decrescente com sorted(Comparator.reverseOrder()),
  3. Depois pulamos o primeiro número com skip(1)
  4. Encontramos o primeiro elemento após o pulo com findFirst()
  5. Como o findFirst() retorna um Optional, precisamos tratar. Usei aqui o método orElse(null) para obter o valor caso exista. Caso contrário, retorna null.
List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 5, 4, 3);

Integer segundoNumero = numeros.stream()
    .distinct()  // Remove elementos repetidos
    .sorted(Comparator.reverseOrder())  // Ordena os números na ordem decrescente
    .skip(1)  // Pula o primeiro número
    .findFirst()  // Encontra o primeiro elemento após o pulo
    .orElse(null);  // Se não encontrar, retorna null

Se ficou alguma dúvida, me avisa que fazemos de outras formas. (:

cami-la avatar Aug 22 '23 16:08 cami-la

Parabéns pela resposta, @siqueirarxd. Muito bom! (:

Não sei se você conhece, mas você também poderia utilizar o método orElseThrow(). Porque daí, já lançamos uma exception caso não exista um segundo maior número.

Exemplo de solução:

List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 5, 4, 3);

Integer segundoNumero = numeros.stream()
    .distinct()  // Remove elementos repetidos
    .sorted(Comparator.reverseOrder())  // Ordena os números na ordem decrescente
    .skip(1)  // Pula o primeiro número
    .findFirst()  // Encontra o primeiro elemento após o pulo
    .orElseThrow(() -> new NoSuchElementException("Não existe segundo maior número."));

Bons estudos para nós!

cami-la avatar Aug 22 '23 16:08 cami-la

Outra maneira de resolver seria ordenando o array de forma crescente e pegando o penúltimo elemento, consequentemente o segundo mais alto. Utilizando também o distinct() para que ele não pegue o elemento mais alto caso o mais alto se repita.

  List<Integer> numerosOrdenado = numeros.stream()
    .sorted()
    .distinct()
    .collect(Collectors.toList());

  int segundoMaisAlto = numerosOrdenado.get(numerosOrdenado.size() - 2));

willianac avatar Aug 31 '23 18:08 willianac

Massa, @willianac. Parabéns! Não tinha pensando em resolver desse jeito. Aprendi mais uma! Obrigada por compartilhar. <3

cami-la avatar Aug 31 '23 18:08 cami-la

Olha como ficou o meu...

public class Desafio7 {
    public static void main(String[] args) {
        List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 5, 4, 10);
        Optional<Integer> primeiroMaior = numeros.stream().max(Integer::compareTo);
        
        Integer x =  numeros.stream().reduce(0, (Integer n, Integer n2)-> {
           return (n2 > n && n2 < primeiroMaior.get()) ? n2 : n;
        });
        System.out.println("Numero reduce: " + x);

    }
}

jpvalim avatar Sep 05 '23 16:09 jpvalim

Parabéns, @jpvalim. Só ficou um mais complexa a solução. Mas chegando no resultado, ótimo! Mais uma vez parabéns pelos estudos! (:

cami-la avatar Sep 10 '23 08:09 cami-la

Usei o limit hehe

numbers.stream().sorted(Collections.reverseOrder()).skip(1).limit(1).forEach(System.out::println);

andersoncpdq avatar Sep 18 '23 00:09 andersoncpdq