Ordenação de Lista

Prezados,

Estou precisando de uma ajuda.

No codigo abaixo estou somando a qtd de um dado codigo de produto. Até ai tudo OK.

Após realizar esse processo, preciso ordenar essa lista em ordem decrescente tendo como base o campo qtd.

Já tentei utilizar o Collections mas nao consegui obter sucesso.

Alguem poderia me ajudar?

A lista que preciso ordenar é a totais

    List<FaturaPedItem> listaPed = d.reltopdezall();

    //pega o tamanho da lista
    int tam = listaPed.size();

    List<TotalPedFatura> totais = new ArrayList<>();
    for (FaturaPedItem item : listaPed) {
        boolean achou = false; // variavel que controla se adiciona na lista de totais ou se somente soma os valores
        // percorre a lista de totais para somar a quantidade do item
        for (TotalPedFatura total : totais) {
            // se a descrição for a mesma, então soma a quantidade
            if (total.codigo_material.equals(item.codigo_material)) {
                total.qtd = total.qtd + item.qtd;
                achou = true;
                break; // aqui interrompe o FOR para não continuar rodando sem necessidade
            }
        }
        // se o item ainda não está na lista de totais, então adiciona um novo
        if (!achou) {
            TotalPedFatura p = new TotalPedFatura();
            p.setCodigo_material(item.codigo_material);
            p.setDescricao(item.descricao);
            p.setQtd(item.qtd);
            totais.add(p);
        }
    }

Acontece que, para que você possa ordenar uma lsita, você precisa criar uma classe que implementa a interface Comparator, por consequência, implementar o método compare desta interface.
Depois disso, você pode utilizar, tranquilamente, o Collections.sort(tuaLista, new ClasseQueImplementaComparator());

Luis eu criei a seguinte classe:

package util;

import vo.FaturaPedItem;
public class Comparacao implements Comparable{

public String getDescricao() {
    return descricao;
}

public void setDescricao(String descricao) {
    this.descricao = descricao;
}

public String getCodigo() {
    return codigo;
}

public void setCodigo(String codigo) {
    this.codigo = codigo;
}

public int getQtd() {
    return qtd;
}

public void setQtd(int qtd) {
    this.qtd = qtd;
}

private String descricao;
private String codigo;
private int qtd;

public Comparacao(String descricao, String codigo, int qtd) {
    super();
    this.descricao = descricao;
    this.codigo = codigo;
    this.qtd = qtd;
}

 public int compareTo(FaturaPedItem carro) {
    if(this.qtd > carro.qtd){
        return -1;
    }
    else if(this.qtd < carro.qtd){
        return 1;
    }
    return this.getCodigo().compareToIgnoreCase(carro.getCodigo_material());
}   

}

e estou fazendo a chamada para o Collections assim:

  Collections.sort(totais, new Comparacao());

Consegue enxergar algum erro no meu codigo?

Mas o que acontece, exatamente? Ele não ordena? Ordena incorretamente?
Para entender, a lista que você quer ordenar é uma lista de que tipo de objeto? E qual é o atributo que está sendo utilizado como argumento para ordenação?

Sobre erros, só vi que você trata os casos de ser menor (retorna -1) ou maior (retorna 1), nunca quando é igual (que retornaria 0). Não sei se interfere no que você está tendo como erro.

Luis,

Não esta nem compilando. Create constructor “Comparacao()” in util.Comparacao.

Eu tenho uma lista que contem codigo, descricao e qtd. O campo que estou utilizando para ordenação é o qtd, pois preciso ordenar de maneira descrecente.

Não consegui visualizar aonde esta o problema.

Esse erro Create constructor "Comparacao()" in util.Comparacao se deve ao fato de que você tem um único construtor na classe Comparacao e ele recebe argumentos

public Comparacao(String descricao, String codigo, int qtd) {
    super();
    this.descricao = descricao;
    this.codigo = codigo;
    this.qtd = qtd;
}

Antes de mais nada, você precisa decidir se vai querer construir um objeto de Comparacao somente com os parâmetros ou se vai ter um construtor sem argumentos.

Quais as diferenças entre o objeto de comparação somente com os parametros e o construtor sem argumentos?

Cara, sério mesmo?
Você precisa voltar ao início dos seus estudos e revisar tudo o que aprendeu até agora.

Quando você tem uma classe assim

public class Foo {
    private int x;

    //getters e setters
}

Ou, a mesma classe, assim

public class Foo {
    private int x;

    public Foo() {
        super();
    }
   
    //getters e setters
}

Você pode criar objetos da classe Foo da seguinte maneira

Foo foo = new Foo();

Pois, mesmo que não haja construtor codificado, o compilador adiciona um muito parecido com o que existe no segundo exemplo.
Acontece que, a partir do momento em que existe um construtor qualquer, o compilador vai trabalhar com aquele construtor. Logo:

public class Foo {
    private int x;

    public Foo(int x) {
        super();
        this.x = x;
    }
       
    //getters e setters
}

Vai transformar esta linha

Foo foo = new Foo();

Em uma linha inválida, já que a única maneira de construir um objeto de Foo é passando um número inteiro em seu construtor

Foo foo = new Foo(10);

É esta a obrigação que você cria quando diz que um objeto da classe Comparacao só pode ser criado se forem passados os parâmetros que o construtor espera

public Comparacao(String descricao, String codigo, int qtd)

Como o método estático sort, de Collections, espera dois objetos como argumento, o primeiro, a coleção a ser ordenada e o segundo o objeto da classe que implementa a interface Comparable, você não está conseguindo fornecer o segundo parâmetro, pois não existe construtor desta classe que não espere parâmetros.

Muito confuso? Vamos imaginar algo mais simples, presente na vida real.
Imagine que você precisa fazer uma omelete.
Basicamente, uma omelete é um objeto da classe Omelete. Para que uma omelete (objeto) exista, é preciso que o construtor da classe Omelete receba os atributos ovos (objetos da classe Ovo).

public class Ovo {
    //atributos
    //métodos
}

e

public class Omelete {
    public Omelete(Ovo[] ovos) {
        //Faz algo aqui
    }
    //atributos
    //métodos
}

É impossível fazer uma omelete (objeto) sem ovos (objetos da classe Ovo).

É óbvio que você pode começar uma omelete com os ingredientes que vai adicionar aos ovos batidos. Com isso, você pode ter algo assim

public class Omelete {
    public Omelete(Ovo[] ovos) {
        //Faz algo aqui
    }

    public Omelete() {
        //Faz alguma coisa aqui
    }
    //atributos
    //métodos
}

Percebe a diferença?
Agora temos a classe Omelete com um construtor que exige ovos e outro que não exige nada (vai que você decide fazer uma omelete sem ovos, tipo, vegana).
Deste modo, você pode criar objetos assim

Omelete omeleteNormal = new Omelete({new Ovo(), new Ovo()});
Ou
Omelete omeleteVegana = new Omelete();

Ficou claro? Alguma dúvida sobre construtores e parâmetros?

1 curtida

Com relação ao teu problema:

Por que me respondeu isso se a pergunta era sobre algo diferente?

Eu preciso que você me detalhe qual a classe que compõe a lista que você quer ordenar e qual é o campo, para te orientar sobre como criar a classe que vai comparar. Só isso.

Perfeito!

Entendi sim.

Luis,

Essa é a classe com os atributos da lista.

Preciso ordenar pelo campo qtd.

package vo;
public class TotalPedFatura {    
   
   public String codigo_material;
   public String descricao;
   public int qtd;
    
    
    public String getCodigo_material() {
        return codigo_material;
    }

    public void setCodigo_material(String codigo_material) {
        this.codigo_material = codigo_material;
    }

    public String getDescricao() {
        return descricao;
    }

    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }

    public int getQtd() {
        return qtd;
    }

    public void setQtd(int qtd) {
        this.qtd = qtd;
    }


}

Eu faria assim

import java.util.Comparator;

public class Ordenacao implements Comparator<TotalPedFatura> {

    @Override
    public int compare(TotalPedFatura one, TotalPedFatura another) {
        if(one.getQtd() > another.getQtd()) {
            return 1;
        } else if(one.getQtd() == another.getQtd()) {
            return -1;
        }
        return 0;
    }

}

E invocaria Collections.sort(listaQueQueroOrdenar, new Ordenacao());

Luis,

O codigo rodou agora sem erros. Porém, não esta ordenando.

 Collections.sort(totais, new Comparacao());
  
   for (TotalPedFatura item : totais) {
       System.out.println(item.getCodigo_material() + " - " + item.getQtd());
   }

Olha a saida:

INFO:   780 - 16620
INFO:   770 - 13902
INFO:   386 - 13253
INFO:   397 - 8453
INFO:   401 - 9947
INFO:   798 - 10522
INFO:   713 - 7169
INFO:   693 - 7495
INFO:   603 - 5621
INFO:   372 - 6159
INFO:   362 - 7045
INFO:   754 - 4707
INFO:   537 - 3997
INFO:   364 - 4747
INFO:   803 - 3407
INFO:   679 - 3203
INFO:   440 - 4613
INFO:   699 - 3151
INFO:   769 - 3816
INFO:   772 - 3001
INFO:   399 - 2385
INFO:   706 - 2247
INFO:   365 - 1244
INFO:   363 - 1188
INFO:   872 - 883
INFO:   402 - 849
INFO:   368 - 841
INFO:   756 - 603

O que deve estar ocorrendo?

Eu fiz uma alteração aqui e funcionou.
Para isso, você precisa fazer com que teu TotalPedFatura implemente Comparator

public class TotalPedFatura implements Comparable<TotalPedFatura> {
    //Outras coisas

    @Override
    public int compareTo(TotalPedFatura another) {
        if(this.getQtd() > another.getQtd()) {
            return 1;
        } else if(this.getQtd() < another.getQtd()) {
            return -1;
        }
        return 0;
    }
    
}

E alterar a classe Ordenacao para

import java.util.Comparator;

public class Ordenacao implements Comparator<TotalPedFatura> {

    @Override
    public int compare(TotalPedFatura one, TotalPedFatura another) {
        return one.compareTo(another);
    }

}

Com isso, certamente você terá teus dados ordenados.

Brother, funcionou!

Muito obrigado!

Olha o resultado. Essa lista alimenta um grafico.

A ultima coisa que vou te pedir…rs

De que maneira possa alterar a logica para que a minha lista fique em ordem descrescente?

Invertendo as comparações no método compareTo, implementado na classe TotalPedFatura. Ao invés do que está lá, retorne conforme abaixo

    @Override
    public int compareTo(TotalPedFatura another) {
        if(this.getQtd() > another.getQtd()) {
            return -1;
        } else if(this.getQtd() < another.getQtd()) {
            return 1;
        }
        return 0;
    }

Ta usando Java 8?

tenta algo do tipo

List<TotalPedFatura> listaOrdenada = totais.stream().sorted(Comparator.comparing(TotalPedFatura::getQtd).reversed()).collect(Collectors.toList());

Luis,

Top demais.

Cara te agradeço demais pela pro-atividade ai e pelo tempo perdido comigo.

Que Deus te abençoe grandemente ai!!!

@jorge.david, nada do que se aprende ou se ensina é tempo perdido.
Para você ter uma ideia, eu nunca tive que implementar uma ordenação, mas sabia das interfaces Comparable e Comparator.
Aliás, olhe com atenção para a dica do @igor_ks, caso você venha a migrar para (ou já use) java 8, ela será de grande valia.

Igor,

Resolvi aqui com a dica do Luis.

Mas vou deixar guardada aqui a sua dica.

Obrigado