Sort using tie-breaker criteria

Asked

Viewed 485 times

0

I need to sort a list of objects with the following criteria:

  • Higher average proficiency levels in each of the
    technical competence required for the task;
  • If the averages are equal, unpack for the lowest price (valorPretendido);
  • If the prices are equal, unpack by the registered Proposal earlier (date);
public class Candidatura{

    private Date date;
    private double valorPretendido;
    private float media;
    private int nrDias;
    private String txtApresentacao;
    private String txtMotivacao;
    int nrCandidaturas = 0;


    public Candidatura (Date dataCandidatura, double valorPretendido, float media, int nrDias, String txtApresentacao,String txtMotivacao) {
        this.setDate(dataCandidatura);
        this.setValorPretendido(valorPretendido);
        this.setMedia(media)
        this.setNrDias(nrDias);
        this.setTxtApresentacao(txtApresentacao);
        this.setTxtMotivacao(txtMotivacao);

        nrCandidaturas++;
}

I’ll have to do the sort several times until there is only one object that can remain after all deletions? It is possible to sort only once to get the "largest" element?

1 answer

3


Yes, you can do everything in one sort.

If you want to make a specific sort, you can use Collections.sort passing a Comparator as a parameter.

The idea of Comparator is to provide a customized comparison form. You simply implement the method compare, receiving two objects obj1 and obj2 and returns the following:

  • if obj1 is "less" than obj2 (that is, if in an ordination obj1 must come before obj2), returns a negative number
  • if obj1 is "greater" than obj2 (that is, if in an ordination obj1 must come after obj2), returns a positive number
  • If it makes the order between them, returns zero

Then given a list of objects, just implement a Comparator that follows the rules you need:

List<Candidatura> list = new ArrayList<>();
// adiciona Candidaturas na lista

Collections.sort(list, new Comparator<Candidatura>() {
    @Override
    public int compare(Candidatura c1, Candidatura c2) {
        int cmp = Double.compare(c2.getMedia(), c1.getMedia());
        if (cmp == 0) { // se as médias forem iguais, desempata pelo menor preço
            cmp = Double.compare(c1.getValorPretendido(), c2.getValorPretendido());
            if (cmp == 0) { // se os preços forem iguais, desempata pela menor data
                cmp = c1.getDate().compareTo(c2.getDate());
            }
        }
        return cmp;
    }            
});

System.out.println(list.get(0));

First I compare the averages. If they are equal (and only if they are equal), I compare the price. If the price is equal, I compare the dates.

Notice that for the average I compared c2 with c1. If I reversed the order, they would be in ascending order, but when reversed, they are in nonexistent order. This means that the highest averages will be at the beginning of the list. Already for the price and date, I put c1 first, because the lowest values must be.

In the end, the element you want will be in the first position (the one that has the highest average, and in the case of a tie on average, the one that has the lowest price, and in the case of a tie on price and the average, the one that has the lowest date). Also remembering that if you have tied in the first position (two elements with the same average, price and date), will be returned what appears first in the list (since the ordering is guaranteed stable).


From Java 8 you can also use the syntax of lambda:

Collections.sort(list, (c1, c2) -> {
    int cmp = Double.compare(c2.getMedia(), c1.getMedia());
    if (cmp == 0) { // se as médias forem iguais, desempata pelo menor preço
        cmp = Double.compare(c1.getValorPretendido(), c2.getValorPretendido());
        if (cmp == 0) { // se os preços forem iguais, desempata pela menor data
            cmp = c1.getDate().compareTo(c2.getDate());
        }
    }
    return cmp;
});
  • 1

    Thank you very much, that was my doubt whether it was possible to do it or not. Thank you very much

Browser other questions tagged

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