1
votes

Interfaces comparables et comparateurs

On dit généralement que le comparateur est utilisé pour avoir plusieurs séquences de tri de collection d'objets tandis que comparable est utilisé pour avoir une séquence de tri unique. À quoi sert l'interface de comparaison en java lorsqu'il est possible d'avoir plusieurs séquences de tri en utilisant une interface comparable?

import java.util.*;
enum CompareValue {RollNo, Marks;}
class Student implements Comparable<Student> {
    public int marks;
    public int rollNo;
    public static CompareValue comparator = CompareValue.RollNo;
    Student (int marks, int rollNo) {
        this.marks = marks;
        this.rollNo = rollNo;
    }
    public int compareTo(Student s) {
        switch (comparator) {
            case RollNo:
                return this.rollNo - s.rollNo;
            case Marks:
                return this.marks - s.marks;
        }
        return 0;
    }
}

public class Test
{
    public static void main (String[] args) 
    {
        Student s1 = new Student(59, 103);
        Student s2 = new Student(87, 102);
        Student s3 = new Student(78, 101);
        Student students[] = {s1, s2, s3};
        Arrays.sort(students);
        System.out.println("Student list sorted by rollno");
        for (Student s:students) {
            System.out.println(s.rollNo + " - " + s.marks);
        }
        Student.comparator = CompareValue.Marks;
        System.out.println("Student list sorted by marks");
        Arrays.sort(students);
        for (Student s:students) {
            System.out.println(s.rollNo + " - " + s.marks);
        }
    }
}


3 commentaires

Vérifiez si cela répond à votre requête stackoverflow.com/questions/1440134/...


Copie possible de Quand une classe doit-elle être Comparable et / ou Comparator?


Votre solution n'est pas thread-safe. Si vous avez deux threads essayant de trier différentes manières en même temps, cela lèverait une exception. Vous devez faire très attention aux champs statiques mutables, et comme ils sont sujets aux erreurs, ils sont souvent considérés comme un hack.


4 Réponses :


0
votes

Lorsque vous avez des objets qui n'implémentent pas de comparables, mais que vous souhaitez trier une collection les comprenant, vous devrez soit les étendre juste pour trier votre collection, soit fournir un comparateur qui les compare même s'ils ne sont pas comparables.

Ou vous voudrez peut-être comparer le tri de ces objets d'une manière différente de leur tri naturel.

Imaginez un tel exemple. String est un objet comparable. Imaginez que vous souhaitiez trier une collection de chaînes en fonction de leur hashCode au lieu de l'ordre naturel des chaînes. Comment feriez-vous sans créer de comparateur?


0 commentaires

0
votes

Ce que vous avez montré, il y a effectivement plusieurs ordres de tri utilisant Comparable , mais ne pensez-vous pas que c'est trop de code de plaque chauffante? Disons que si vous avez ajouté un nouveau champ à la classe appelée nom , et que vous souhaitez maintenant trier par nom. Vous devrez:

  • ajouter un nouveau cas à l'énumération
  • ajoutez un nouveau cas au compareTo .

Un autre inconvénient de l'utilisation de l'approche que vous avez montrée est que ce que cela signifie n'est pas forcément clair:

Arrays.sort(students, Comparator.comparing(Student::getName));

Vous devrez parcourir votre code et Vérifiez la valeur que vous avez définie pour le comparator .

De plus, si j'utilisais votre classe et que je veux trier par autre chose, je devrais créer un Comparator de toute façon, car je ne peux pas modifier votre classe.

Mais si vous utilisez Comparator , vous résolvez tous ces problèmes:

Arrays.sort(student);

Par conséquent, Comparable n'est utile que lorsqu'il y a un ordre naturel, comme les dates et les heures par exemple.


0 commentaires

1
votes

Lorsque votre méthode compareTo a des comportements différents en fonction de la valeur d'une variable statique , vous introduisez essentiellement un paramètre global qui contrôle l'ordre naturel du Classe d'élève .

Cela peut être déroutant et contre-intuitif pour les utilisateurs de votre classe.

De plus, cela rend l'implémentation de compareTo délicate, surtout si vous avez plus de deux implémentations, et chaque implémentation dépend de plusieurs variables d'instance.

Comparator est une interface beaucoup plus appropriée pour fournir plusieurs comparaisons différentes pour des instances de la même classe, chaque implémentation ayant sa propre logique compare () .


0 commentaires

0
votes

Si nous regardons les interfaces Comparable et Comparator et ce qu'elles signifient, tout sera clair.

Comparable:

C'est une propriété interne d'une classe JAVA c'est-à-dire qu'elle suppose que chaque fois que l'on utilise la méthode interne compareTo () , on l'utilise pour l'objet spécifié.

int compare(T o1, T o2);

Par conséquent, dans l'implémentation de cette méthode, nous utilisons this qui est l'objet actuel et le comparons à un autre objet du même type . Ceux-ci peuvent être traités comme des valeurs par défaut ou utilisés pour un ordre naturel.
Comme 1 vient avant 2 et ainsi de suite. C'est l'ordre naturel.

Comparateur:

C'est une propriété qui n'est en fait pas étroitement liée à la classe Java elle-même. Les comparateurs sont utilisés pour fournir en fait une méthode à utiliser par certains autres services (comme Collections.sort () ) pour atteindre un objectif particulier.

public int compareTo(T o);

Nous entendons par là que vous pouvez avoir plusieurs comparateurs, offrant différentes manières d'atteindre différents objectifs dans lesquels le service réel peut choisir deux objets et les comparer.
Cela peut être utilisé pour fournir un ordre personnalisé, comme en utilisant une équation, nous pouvons trouver un ordre où f (1) vient en fait après f (2) et ainsi de suite. Cette équation atteindra probablement un certain ordre qui résoudra un cas d'utilisation.


0 commentaires