83 votes

Triage à l'aide d'un comparateur - Ordre décroissant (classes définies par l'utilisateur)

Je veux trier mes objets par ordre décroissant en utilisant un comparateur.

class Person {
 private int age;
}

Ici, je veux trier un tableau d'objets Personne.

Comment puis-je le faire ?

124voto

namxal Points 307

Vous pouvez effectuer le tri descendant d'une classe définie par l'utilisateur de cette manière en surchargeant la fonction comparer() méthode,

Collections.sort(unsortedList,new Comparator<Person>() {
    @Override
    public int compare(Person a, Person b) {
        return b.getName().compareTo(a.getName());
    }
});

Ou en utilisant Collection.reverse() pour trier en ordre décroissant comme utilisateur Prince mentionné dans son commentaire .

Et vous pouvez faire le tri ascendant comme ceci,

Collections.sort(unsortedList,new Comparator<Person>() {
    @Override
    public int compare(Person a, Person b) {
        return a.getName().compareTo(b.getName());
    }
});

Remplacez le code ci-dessus par une expression Lambda (à partir de Java 8) et vous obtiendrez un code concis :

Collections.sort(personList, (Person a, Person b) -> b.getName().compareTo(a.getName()));

À partir de Java 8, List a trier() qui prend Comparateur comme paramètre (plus concis) :

personList.sort((a,b)->b.getName().compareTo(a.getName()));

Ici a y b sont déduits comme type de personne par l'expression lambda.

69voto

camickr Points 137095

Pour ce que ça vaut, voici ma réponse standard. La seule chose nouvelle ici est qu'elle utilise la fonction Collections.reverseOrder(). De plus, toutes les suggestions sont regroupées dans un seul exemple :

/*
**  Use the Collections API to sort a List for you.
**
**  When your class has a "natural" sort order you can implement
**  the Comparable interface.
**
**  You can use an alternate sort order when you implement
**  a Comparator for your class.
*/
import java.util.*;

public class Person implements Comparable<Person>
{
    String name;
    int age;

    public Person(String name, int age)
    {
        this.name = name;
        this.age = age;
    }

    public String getName()
    {
        return name;
    }

    public int getAge()
    {
        return age;
    }

    public String toString()
    {
        return name + " : " + age;
    }

    /*
    **  Implement the natural order for this class
    */
    public int compareTo(Person p)
    {
        return getName().compareTo(p.getName());
    }

    static class AgeComparator implements Comparator<Person>
    {
        public int compare(Person p1, Person p2)
        {
            int age1 = p1.getAge();
            int age2 = p2.getAge();

            if (age1 == age2)
                return 0;
            else if (age1 > age2)
                return 1;
            else
                return -1;
        }
    }

    public static void main(String[] args)
    {
        List<Person> people = new ArrayList<Person>();
        people.add( new Person("Homer", 38) );
        people.add( new Person("Marge", 35) );
        people.add( new Person("Bart", 15) );
        people.add( new Person("Lisa", 13) );

        // Sort by natural order

        Collections.sort(people);
        System.out.println("Sort by Natural order");
        System.out.println("\t" + people);

        // Sort by reverse natural order

        Collections.sort(people, Collections.reverseOrder());
        System.out.println("Sort by reverse natural order");
        System.out.println("\t" + people);

        //  Use a Comparator to sort by age

        Collections.sort(people, new Person.AgeComparator());
        System.out.println("Sort using Age Comparator");
        System.out.println("\t" + people);

        //  Use a Comparator to sort by descending age

        Collections.sort(people,
            Collections.reverseOrder(new Person.AgeComparator()));
        System.out.println("Sort using Reverse Age Comparator");
        System.out.println("\t" + people);
    }
}

20voto

Andreas_D Points 64111

Je voudrais créer un comparateur pour la classe de personne qui peut être paramétré avec un certain comportement de tri. Ici, je peux définir l'ordre de tri, mais il peut être modifié pour permettre le tri d'autres attributs de la personne.

public class PersonComparator implements Comparator<Person> {

  public enum SortOrder {ASCENDING, DESCENDING}

  private SortOrder sortOrder;

  public PersonComparator(SortOrder sortOrder) {
    this.sortOrder = sortOrder;
  }

  @Override
  public int compare(Person person1, Person person2) {
    Integer age1 = person1.getAge();
    Integer age2 = person2.getAge();
    int compare = Math.signum(age1.compareTo(age2));

    if (sortOrder == ASCENDING) {
      return compare;
    } else {
      return compare * (-1);
    }
  }
}

(j'espère que ça compile maintenant, je n'ai pas d'IDE ou de JDK sous la main, j'ai codé 'à l'aveugle')

Modifier

Merci à Thomas, j'ai modifié le code. Je ne dirais pas que l'utilisation de Math.signum est bonne, performante, efficace, mais j'aimerais le garder pour rappeler que la méthode compareTo peut retourner n'importe quel entier et que la multiplication par (-1) échouera si l'implémentation retourne Integer.MIN_INTEGER... Et j'ai supprimé le setter parce que c'est assez bon marché de construire un nouveau PersonComparator juste quand c'est nécessaire.

Mais je garde la boîte parce que cela montre que je m'appuie sur une implémentation existante de Comparable. On aurait pu faire quelque chose comme Comparable<Integer> age1 = new Integer(person1.getAge()); mais ça avait l'air trop moche. L'idée était de montrer un modèle qui pourrait facilement être adapté à d'autres attributs de la personne, comme le nom, l'anniversaire en tant que date, etc.

16voto

Thomas Jung Points 17692
String[] s = {"a", "x", "y"};
Arrays.sort(s, new Comparator<String>() {

    @Override
    public int compare(String o1, String o2) {
        return o2.compareTo(o1);
    }
});
System.out.println(Arrays.toString(s));

-> [y, x, a]

Maintenant, vous devez implémenter le Comparateur pour votre classe Personne. Quelque chose comme (pour un ordre croissant) : compare(Person a, Person b) = a.id < b.id ? -1 : (a.id == b.id) ? 0 : 1 o Integer.valueOf(a.id).compareTo(Integer.valueOf(b.id)) .

Pour minimiser la confusion, vous devriez implémenter un comparateur ascendant et le convertir en un comparateur descendant avec un wrapper ( comme ceci ) new ReverseComparator<Person>(new PersonComparator()) .

5voto

finnw Points 24592

Utilisation de Google Collections :

class Person {
 private int age;

 public static Function<Person, Integer> GET_AGE =
  new Function<Person, Integer> {
   public Integer apply(Person p) { return p.age; }
  };

}

public static void main(String[] args) {
 ArrayList<Person> people;
 // Populate the list...

 Collections.sort(people, Ordering.natural().onResultOf(Person.GET_AGE).reverse());
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X