cami-la / collections-java-api-2023

Este repositório é referente ao curso "Collection Framework API Java" e é uma valiosa contribuição para a comunidade de desenvolvedores Java, fornecendo exemplos práticos e recursos educacionais relacionados à poderosa API de coleções da linguagem Java.
https://web.dio.me/course/conhecendo-collections-java/learning/c5d6f4e1-6d05-4eea-93d8-d292c708999f
876 stars 636 forks source link

Map Ordenação LivrariaOnline - exibirLivrosOrdenadosPorPreco(), #21

Open Udinei opened 10 months ago

Udinei commented 10 months ago

Boa tarde! Camila!

Fazendo os exercicios de Map e nalisando o retorno do metodo exibirLivrosOrdenadosPorPreco(), me parece que esse metodo não esta ordenando corretamente, mesmo usando o Comparable, ou Comparator que também da o mesmo resultado?.

Baixei suas classes e deu o mesmo resultado, pra mim o retorno não esta correto!

Dei um pesquisada e vi alguns exemplos para fazer essa ordenação, mas achei muito complexos! Pode verficar por favor e dar um retorno?

Vou continuar pesquisando aqui uma forma mais simples de fazer isso!

Obrigado!!

Udinei commented 10 months ago

Bom dia Camila!

Consegui fazer! Esse foi o exemplo mais simples que consegui implementar, os outros ficaram muito complexos!

public void exibirLivrosOrdenadosPorPreco() {
TreeMap<Double, Livro> livrosOrdenados = new TreeMap<>(new Comparator() {

     @Override
        public int compare(Double preco1, Double preco2) {
            return Double.compare(preco1, preco2);
        }
    });

    System.out.println(livrosOrdenados.entrySet());
    for (var entry : livrosMap.entrySet()) {
        Livro livro = entry.getValue();
        double preco = livro.getPreco();
        livrosOrdenados.put(preco, entry.getValue());
    }

    System.out.println(livrosOrdenados);

}`
cami-la commented 10 months ago
  1. Vamos criar um Comparator para definir a forma que queremos organizar os elementos dentro do Map:
class ComparatorPorPreco implements Comparator<Map.Entry<String, Livro>> {
  @Override
  public int compare(Map.Entry<String, Livro> l1, Map.Entry<String, Livro> l2) {
    return Double.compare(l1.getValue().getPreco(), l2.getValue().getPreco());
  }
}
  1. Separamos apenas os valores (objetos do tipo Livro), já que é a partir do atributo preco que vamos querer ordenar nosso Map.

  2. Estamos utilizando o método livros.entrySet() porque queremos que a chave e o valor tenham uma "ligação".

List<Map.Entry<String, Livro>> livrosParaOrdenarPorPreco = new ArrayList<>(livros.entrySet());
  1. Agora que temos uma collection do tipo List, podemos facilmente ordenar esses valores utilizando o Collections:

    Collections.sort(livrosParaOrdenarPorPreco, new ComparatorPorPreco());
  2. Já temos os elementos ordenados dentro de um List, porém, precisamos passar novamente para um Map. Para manter a ordem dos elementos a medida que nós inserimos os elementos ordanados dentro de um Map, podemos utilizar a implementação LinkedHashMap.

Map<String, Livro> livrosOrdenadosPorPreco = new LinkedHashMap<>();
  1. Vamos popular o Map livrosOrdenadosPorPreco:
    for (Map.Entry<String, Livro> entry : livrosParaOrdenarPorPreco) {
      livrosOrdenadosPorPreco.put(entry.getKey(), entry.getValue());
    }
  2. Agora sim, podemos retornar livrosOrdenadosPorPreco.
public Map<String, Livro> exibirLivrosOrdenadosPorPreco() {
    List<Map.Entry<String, Livro>> livrosParaOrdenarPorPreco = new ArrayList<>(livros.entrySet());

    Collections.sort(livrosParaOrdenarPorPreco, new ComparatorPorPreco());

    Map<String, Livro> livrosOrdenadosPorPreco = new LinkedHashMap<>();

    for (Map.Entry<String, Livro> entry : livrosParaOrdenarPorPreco) {
      livrosOrdenadosPorPreco.put(entry.getKey(), entry.getValue());
    }

    return livrosOrdenadosPorPreco;
  }

Também criei o método exibirLivrosOrdenadosPorAutor():

public Map<String, Livro> exibirLivrosOrdenadosPorAutor() {
    List<Map.Entry<String, Livro>> livrosParaOrdenarPorAutor = new ArrayList<>(livros.entrySet());

    Collections.sort(livrosParaOrdenarPorAutor, new ComparatorPorAutor());

    Map<String, Livro> livrosOrdenadosPorAutor = new LinkedHashMap<>();

    for (Map.Entry<String, Livro> entry : livrosParaOrdenarPorAutor) {
      livrosOrdenadosPorAutor.put(entry.getKey(), entry.getValue());
    }

    return livrosOrdenadosPorAutor;
  }

Veja que é praticamente a mesma coisa. Seguindo os exemplos acima, deixo como desafio, você tentar implementar o método exibirLivrosOrdenadosPorTitulo().

Ah, pode instanciar o new Comparator dentro do método exibirLivrosOrdenadosPorTitulo() como você vem fazendo, ok? Gosto de criar uma classe fora só por organização mesmo. (:

cami-la commented 10 months ago

Bom dia Camila!

Consegui fazer! Esse foi o exemplo mais simples que consegui implementar, os outros ficaram muito complexos!

public void exibirLivrosOrdenadosPorPreco() {
TreeMap<Double, Livro> livrosOrdenados = new TreeMap<>(new Comparator() {

     @Override
        public int compare(Double preco1, Double preco2) {
            return Double.compare(preco1, preco2);
        }
    });

    System.out.println(livrosOrdenados.entrySet());
    for (var entry : livrosMap.entrySet()) {
        Livro livro = entry.getValue();
        double preco = livro.getPreco();
        livrosOrdenados.put(preco, entry.getValue());
    }

    System.out.println(livrosOrdenados);

}`

Oi, @Udinei. Meus parabéns, sua implementação ficou ótima! Porém tem um detalhe: Veja que você modificou o tipo da chave do map: TreeMap<Double, Livro> livrosOrdenados = new TreeMap<>();

No nosso exercício, o Map contém as chave String (que representa o link do Livro) e o valor é o objeto do tipo Livro. Isso é um problema? Não, de forma alguma. Mas acima, implementei de uma outra forma sem modificar o tipo original da chave e valor do Map e te deixei um desafio. (:

De fato, quando queremos ordenar um Map através do value e não da key é um pouco mais trabalhoso. Mas você está indo muito bem! Se ficou alguma dúvida, fico à disposição. E agradeço pela issue, assim eu pude corrigir e melhorar os exercícios.