web-dev-qa-db-fra.com

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

Je souhaite développer une démo de tri pour la liste des voitures. J'utilise un tableau de données pour afficher la liste des voitures. Maintenant, en fait, je veux trier la liste par couleur de voiture. Ici, il n’est pas trié par ordre alphabétique. Je souhaite utiliser mon ordre de tri personnalisé, comme les voitures rouges d'abord, puis bleues, etc.

Pour cela j'essaie d'utiliser Java Comparator et Comparable ) mais cela permet de trier alphabétiquement ordre seulement.

Alors, est-ce que quelqu'un peut me guider pour implémenter la technique à utiliser afin 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             
    }
}
78
akhtar

Je vous recommande de créer un enum pour les couleurs de votre voiture plutôt que d'utiliser des chaînes et l'ordre naturel de cet enum sera l'ordre dans lequel vous déclarerez les constantes.

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

et

 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 de votre voiture devient:

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

...

Collections.sort(carList, new ColorComparator());
96
z7sg Ѫ

Que dis-tu de ça:

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 conviens que l’utilisation de enum est une approche encore meilleure, mais cette version est plus souple car elle vous permet de définir différents ordres de tri.

Mettre à jour

Guava intègre cette fonctionnalité dans sa 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 commentée.


Mettre à jour à nouveau

Java 8 rend le comparateur encore moins bavard:

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

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());
    }
});
22
Silvio Troia

Je pense que cela peut être fait comme suit:

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));
9
ilalex

Je devais faire quelque chose de similaire à la réponse de Sean et ilalex.
Mais j'avais trop d'options pour définir explicitement l'ordre de tri et je n'avais besoin que de faire flotter certaines entrées au début de la 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
}
7
matt1616

Dans Java 8, vous pouvez faire quelque chose comme ceci:

Vous avez d'abord besoin d'un énum:

public enum Color {
    BLUE, YELLOW, RED
}

Classe de voiture:

public class Car {

    Color color;

    ....

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }
}

Et ensuite, en utilisant votre liste de voitures, vous pouvez simplement faire:

Collections.sort(carList, Comparator:comparing(CarSort::getColor));
2
Thermech

Définir un type d'énumération comme

public enum Colors {
     BLUE, SILVER, Magenta, RED
}

Changer le type de données de color de String en Colors Changer le type de retour et le type d'argument de la méthode getter et setter de color en Colors

Définir le type de comparateur comme suit

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

après avoir ajouté des éléments à la liste, appelez la méthode de tri de Collection en transmettant comme arguments les objets liste et comparateur.

c'est-à-dire Collections.sort(carList, new ColorComparator()); puis imprimez avec ListIterator.

l'implémentation complète de la classe est la suivante:

package test;

import Java.util.ArrayList;
import Java.util.Collections;
import Java.util.Comparator;
import Java.util.List;    
import Java.util.ListIterator;

public class CarSort implements Comparable<CarSort>{

    String name;
    Colors color;

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

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Colors getColor() {
        return color;
    }
    public void setColor(Colors color) {
        this.color = color;
    }

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

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

    public enum Colors {
         BLUE, SILVER, Magenta, RED
    }

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

         carList.add(new CarSort("Ford Figo",Colors.SILVER));
         carList.add(new CarSort("Santro",Colors.BLUE));
         carList.add(new CarSort("Honda Jazz",Colors.Magenta));
         carList.add(new CarSort("Indigo V2",Colors.RED));
         Collections.sort(carList, new ColorComparator());

         ListIterator<CarSort> itr=carList.listIterator();
         while (itr.hasNext()) {
            CarSort carSort = (CarSort) itr.next();
            System.out.println("Car colors: "+carSort.getColor());
        }
     }
}
2
Siddu