112 votes

Comment utiliser le comparateur pour définir un ordre de tri personnalisé ?

Je souhaite développer une démonstration de tri pour une liste de voitures. J'utilise un tableau de données pour afficher la liste des voitures. Maintenant, je veux trier la liste par couleur de voiture. Ici, le tri ne se fait pas par ordre alphabétique. Je veux utiliser mon propre ordre de tri, comme par exemple la voiture rouge vient en premier, puis la bleue, etc.

Pour cela, j'essaie d'utiliser Java Comparator y Comparable mais il ne permet de trier que par ordre alphabétique.

Donc, quelqu'un peut-il me guider sur la façon de mettre en œuvre la technique à utiliser pour que le tri devienne plus rapide.

class Car implements Comparable<Car>
{
    private String name;
    private String color;

    public Car(String name, String color){
        this.name = name;
        this.color = color;
    }

    //Implement the natural order for this class
    public int compareTo(Car c) {
        return name.compareTo(c.name);
    }

    static class ColorComparator implements Comparator<Car> {
        public int compare(Car c1, Car c2) {
            String a1 = c1.color;
            String a2 = c2.color;
            return a1.compareTo(a2);
        }
    }

    public static void main(String[] args) {
        List<Car> carList = new ArrayList<>();
        List<String> sortOrder = new ArrayList<>();

        carList.add(new Car("Ford","Silver"));
        carList.add(new Car("Tes","Blue"));
        carList.add(new Car("Honda","Magenta"));

        sortOrder.add("Silver");
        sortOrder.add("Magenta");
        sortOrder.add("Blue");

        // Now here I am confuse how to implement my custom sort             
    }
}

113voto

z7sg Ѫ Points 1420

Je vous recommande de créer une énumération pour les couleurs de vos voitures au lieu d'utiliser des chaînes de caractères et l'ordre naturel de l'énumération sera l'ordre dans lequel vous déclarez les constantes.

public enum PaintColors {
    SILVER, BLUE, MAGENTA, RED
}

y

 static class ColorComparator implements Comparator<CarSort>
 {
     public int compare(CarSort c1, CarSort c2)
     {
         return c1.getColor().compareTo(c2.getColor());
     }
 }

Vous changez la chaîne en PaintColor et dans la liste principale, votre liste de voitures devient :

carList.add(new CarSort("Ford Figo",PaintColor.SILVER));

...

Collections.sort(carList, new ColorComparator());

75voto

Sean Patrick Floyd Points 109428

Que pensez-vous de ceci ?

List<String> definedOrder = // define your custom order
    Arrays.asList("Red", "Green", "Magenta", "Silver");

Comparator<Car> comparator = new Comparator<Car>(){

    @Override
    public int compare(final Car o1, final Car o2){
        // let your comparator look up your car's color in the custom order
        return Integer.valueOf(
            definedOrder.indexOf(o1.getColor()))
            .compareTo(
                Integer.valueOf(
                    definedOrder.indexOf(o2.getColor())));
    }
};

En principe, je suis d'accord pour dire que l'utilisation d'un enum est une approche encore meilleure, mais cette version est plus flexible car elle vous permet de définir différents ordres de tri.

Mise à jour

Goyave dispose de cette fonctionnalité dans son Ordering classe :

List<String> colorOrder = ImmutableList.of("red","green","blue","yellow");
final Ordering<String> colorOrdering = Ordering.explicit(colorOrder);
Comparator<Car> comp = new Comparator<Car>() {
    @Override
    public int compare(Car o1, Car o2) {
        return colorOrdering.compare(o1.getColor(),o2.getColor());
    }
}; 

Cette version est un peu moins verbeuse.


Nouvelle mise à jour

Java 8 rend le comparateur encore moins verbeux :

Comparator<Car> carComparator = Comparator.comparing(
        c -> definedOrder.indexOf(c.getColor()));

26voto

Silvio Troia Points 353

Comparateur en ligne ...

List<Object> objList = findObj(name);
Collections.sort(objList, new Comparator<Object>() {
    @Override
    public int compare(Object a1, Object a2) {
        return a1.getType().compareToIgnoreCase(a2.getType());
    }
});

15voto

ilalex Points 1319

Je pense que cela peut se faire de la manière suivante :

class ColorComparator implements Comparator<CarSort>
{
    private List<String> sortOrder;
    public ColorComparator (List<String> sortOrder){
        this.sortOrder = sortOrder;
    }

    public int compare(CarSort c1, CarSort c2)
    {
        String a1 = c1.getColor();
        String a2 = c2.getColor();
        return sortOrder.indexOf(a1) - sortOrder.indexOf(a2);
     }
 }

Pour le tri, utilisez ceci :

Collections.sort(carList, new ColorComparator(sortOrder));

8voto

matt1616 Points 78

J'ai dû faire quelque chose de similaire à la réponse de Sean et d'ilalex.
Mais j'avais trop d'options pour définir explicitement l'ordre de tri et j'avais seulement besoin de placer certaines entrées en tête de liste ... dans l'ordre spécifié (non naturel).
J'espère que cela sera utile à quelqu'un d'autre.

public class CarComparator implements Comparator<Car> {

    //sort these items in this order to the front of the list 
    private static List<String> ORDER = Arrays.asList("dd", "aa", "cc", "bb");

    public int compare(final Car o1, final Car o2) {
        int result = 0;
        int o1Index = ORDER.indexOf(o1.getName());
        int o2Index = ORDER.indexOf(o2.getName());
        //if neither are found in the order list, then do natural sort
        //if only one is found in the order list, float it above the other
        //if both are found in the order list, then do the index compare
        if (o1Index < 0 && o2Index < 0) result = o1.getName().compareTo(o2.getName());
        else if (o1Index < 0) result = 1;
        else if (o2Index < 0) result = -1;
        else result = o1Index - o2Index;
        return result;
    }

//Testing output: dd,aa,aa,cc,bb,bb,bb,a,aaa,ac,ac,ba,bd,ca,cb,cb,cd,da,db,dc,zz
}

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