Sort a list of objects by more than one attribute

Asked

Viewed 5,037 times

3

How to sort a list of objects by more than one attribute? First is made the ordering of the score, then as tiebreaker criteria we have the winning number and then the goal balance.

Something like that:

Pontuacao pontuacao = new Pontuacao(pontos, vitórias, saldo de gols);

List lista = new List();

Pontuacao timeA = new Pontuacao(14, 6, 20);

lista.add(timeA);

Pontuacao timeB = new Pontuacao(18, 3, 21);

lista.add(timeB);

Pontuacao timeC = new Pontuacao(14, 6, 22);

lista.add(timeC);

Pontuacao timeD = new Pontuacao(15, 7, 11);

lista.add(timeD);

lista.sort;

Upshot:

1º) timeB // Highest score

2º) timed // Second highest score

3º) timeC // Largest goal balance

4º) Timea

2 answers

3


To do this sort, you can use the method sort class Collections. Through it, you can create a block ordering logic:

List<Pontuacao> pontuacoes = new ArrayList<>();
    pontuacoes.add(new Pontuacao(14, 6, 20));
    pontuacoes.add(new Pontuacao(18, 3, 21));
    pontuacoes.add(new Pontuacao(14, 6, 22));
    pontuacoes.add(new Pontuacao(15, 7, 11));

    Collections.sort(pontuacoes, new Comparator<Pontuacao>() {
        @Override
        public int compare(Pontuacao lhs, Pontuacao rhs) {
            if(lhs.getPontos != rhs.getPontos)
                return Integer.compare(lhs.getPontos(), rhs.getPontos());
            else if(lhs.getVitorias() != rhs.getVitorias())
                return Integer.compare(lhs.getVitorias(), rhs.getVitorias());
            return Integer.compare(lhs.getSaldoDeGols(), rhs.getSaldoDeGols());
        }
    });

Your Score object can even implement the interface Comparable<T> to make this code more organized:

class Pontuacao implements Comparable<Pontuacao> {
    private int pontos;
    private int vitorias;
    private int saldoDeGols;

    public Pontuacao(int pontos, int vitorias, int saldoDeGols) {
        this.pontos = pontos;
        this.vitorias = vitorias;
        this.saldoDeGols = saldoDeGols;
    }

    public int getPontos() {
        return pontos;
    }

    public void setPontos(int pontos) {
        this.pontos = pontos;
    }

    public int getVitorias() {
        return vitorias;
    }

    public void setVitorias(int vitorias) {
        this.vitorias = vitorias;
    }

    public int getSaldoDeGols() {
        return saldoDeGols;
    }

    public void setSaldoDeGols(int saldoDeGols) {
        this.saldoDeGols = saldoDeGols;
    }

    @Override
    public int compareTo(@NonNull Pontuacao another) {
        if(another.getPontos() != getPontos())
            return Integer.compare(another.getPontos(), getPontos());
        else if(another.getVitorias() != getVitorias())
            return Integer.compare(another.getVitorias(), getVitorias());
        return Integer.compare(another.getSaldoDeGols(), getSaldoDeGols());
    }
}

So, Sort gets simplicate:

List<Pontuacao> pontuacoes = new ArrayList<>();
    pontuacoes.add(new Pontuacao(14, 6, 20));
    pontuacoes.add(new Pontuacao(18, 3, 21));
    pontuacoes.add(new Pontuacao(14, 6, 22));
    pontuacoes.add(new Pontuacao(15, 7, 11));

    Collections.sort(pontuacoes);
  • 1

    We were teaching the OP to fish instead of giving the fish... and also the logic of the comparison is incorrect.

  • ...or not. L:^)

  • What are setters for? To be able to change the score after the list has been ordered and thus invalidate the ordering? Since you suggested the full code, I suggest suggesting an immutable class for the Score object.

  • @Caffé, the setters are results of a class generation plugin with getters/setters that I used to create the example. I did not bother to remove them, or create the class in hand. I apologize for creating the answer with code. If you like, I remove

  • There’s nothing to be sorry about, @Igorcastañedaferreira. The answer is yours (you say it) and it’s good.

2

Take your class Pontuacao implement the interface Comparable<Pontuacao> and implement in it the method compareTo().

Example with two criteria, criterion 1 being more important and criterion 2 being less important:

public int compareTo(Pontuacao outro) {
    int resultado = outro.getCriterio1() - this.getCriterio1();
    if (resultado == 0) {
        resultado = outro.getCriterio2() - this.getCriterio2();
    }

    return resultado;
}

Why don’t you have a null check?

  • That’s what I thought and saw in a number of examples, but doubt is how to sort by more than one attribute following the order of importance. Like Order by do sql.

  • 1

    In the compareTo you will compare two teams by the number of points. If they are equal, you will compare them according to the highest score. And if the score is equal, it will compare by the goal balance. In the end you will have to return a negative number, positive or zero, depending on the result of the comparisons.

  • 2

    @Run You sort by more than one attribute the same way you sort by a single attribute - you’ll only have more than one condition in comparison. If you’ve seen examples, update your question with what you’ve managed to do so far.

  • Well, with the given fish, I’ll supplement the answer.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.