2009-12-22 4 views

Répondre

14
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] 

Vous devez maintenant implémenter la comparaison pour votre classe Person. Quelque chose comme (pour l'ordre croissant): compare(Person a, Person b) = a.id < b.id ? -1 : (a.id == b.id) ? 0 : 1 ou Integer.valueOf(a.id).compareTo(Integer.valueOf(b.id)).

Pour minimiser la confusion, vous devez implémenter un comparateur ascendant et le convertir en un élément descendant avec un wrapper (like this) new ReverseComparator<Person>(new PersonComparator()).

+0

Voici un exemple un peu déroutant, car String implémente Comparable. Et cela - il n'y a pas la chose la plus directe. – Bozho

+1

Le meilleur argument contre -1 * x est que -1 -1 Integer.MIN_VALUE == Integer.MIN_VALUE'. Ce n'est pas ce que tu veux. J'ai échangé les arguments qui sont plus faciles de toute façon. –

+1

Et je suppose que c'est un ReverseComparator, au lieu de Reserve ... –

0

La classe s java.util.Collection a une méthode de tri qui prend une liste et un Comparator personnalisé. Vous pouvez définir votre propre comparateur pour trier votre objet Person comme bon vous semble.

0
package com.test; 

import java.util.Arrays; 

public class Person implements Comparable { 

private int age; 

private Person(int age) { 
    super(); 
    this.age = age; 
} 

public int getAge() { 
    return age; 
} 

public void setAge(int age) { 
    this.age = age; 
} 

@Override 
public int compareTo(Object o) { 
    Person other = (Person)o; 
    if (this == other) 
     return 0; 
    if (this.age < other.age) return 1; 
    else if (this.age == other.age) return 0; 
    else return -1; 

} 

public static void main(String[] args) { 

    Person[] arr = new Person[4]; 
    arr[0] = new Person(50); 
    arr[1] = new Person(20); 
    arr[2] = new Person(10); 
    arr[3] = new Person(90); 

    Arrays.sort(arr); 

    for (int i=0; i < arr.length; i++) { 
     System.out.println(arr[i].age); 
    } 
} 

} 

Voici une façon de le faire.

13

Je créerais un comparateur pour la classe de personnes 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 des attributs d'autres personnes.

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); 
    } 
    } 
} 

(espérons qu'il compile maintenant, je ne IDE ou JDK à portée de main, codées 'aveugle')

Modifier

Merci à Thomas, édité le code. Je ne dirais pas que l'utilisation de Math.signum est bonne, performante, efficace, mais je voudrais garder cela comme un rappel, que la méthode compareTo peut renvoyer n'importe quel nombre entier et multiplier par (-1) échouera si le L'implémentation retourne Integer.MIN_INTEGER ... Et j'ai enlevé le setter parce que c'est assez bon marché pour construire un nouveau PersonComparator juste quand c'est nécessaire.

Mais je garde la boxe parce qu'elle montre que je me base sur une implémentation comparable existante. Pourrait avoir fait quelque chose comme Comparable<Integer> age1 = new Integer(person1.getAge()); mais cela 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 comme date et ainsi de suite.

+4

Il était une fois une bonne habitude de laisser un commentaire pour aider l'auteur juste downvoted à améliorer son message. –

+0

Je n'ai pas downvote, mais 'compare * (-1)' est sujette au débordement. J'ai fait la même erreur dans mon message initial. –

+0

Et le SortOrder doit être défini dans le constructeur et être final. Utiliser un wrapper est une meilleure approche que je suppose: 'new Reverse (new PersonComparator())' –

4

Utilisation des collections Google:

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()); 
} 
+2

Dépassement avec le style :) – Esko

58
Pour ce qui est

sa valeur voici ma réponse standard. La seule nouveauté ici est l'utilisation de Collections.reverseOrder(). De plus, il met toutes les suggestions en 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); 
    } 
} 
+0

cela a fonctionné réellement pour moi, et c'est aussi une solution très facile (juste une ligne). –

+0

Exemple parfait! Merci. –

+0

Existe-t-il un moyen de trier les chaînes dans un TreeSet en utilisant un comparateur comme celui-ci? Même chose, les gens par âge. – Zeff520

82

Vous pouvez faire le tri descendant d'une classe définie par l'utilisateur ainsi redéfinissant la méthode compare(),

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 descendant en tant qu'utilisateur Prince mentionné dans his comment.

Et vous pouvez faire le tri croissant comme celui-ci,

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 avec une expression Lambda (Java 8 et suivantes) nous obtenons concis:

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

A partir de Java 8, liste a procédé sort() qui prend comme paramètre Comparator (plus concise):

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

Ici a et b sont induits en tant que type de personne par expression lambda.

+18

Ou vous pouvez simplement utiliser 'Collections.reverseOrder (...)' pour le tri décroissant. – Prince

+1

@Prince Pas un fan de cette approche, il me force à regarder la méthode originale pour voir comment les choses sont triées pour commencer (non-inversé.) –

+1

Il vaut la peine de mentionner que 'compareToIgnoreCase' est également utile lors de la comparaison des objets' String' , plus souvent qu'autrement, j'utilise ceci au lieu de juste 'compareTo' –

Questions connexes