Comparateur et Comparable en Java

Comparateur et Comparable en Java

1. introduction

Les comparaisons en Java sont assez faciles - jusqu'à ce qu'elles ne le soient pas.

Lorsque vous travaillez avec des types personnalisés ou que vous essayez de comparer des objets qui ne sont pas directement comparables, nous devons utiliser une stratégie de comparaison. Nous pouvons en construire un simplement, mais en utilisant les interfacesComparator ouComparable.

2. Mise en place de l'exemple

Prenons l'exemple d'une équipe de football - où nous voulons aligner les joueurs en fonction de leur classement.

Nous allons commencer par créer une simple classePlayer:

public class Player {
    private int ranking;
    private String name;
    private int age;

    // constructor, getters, setters
}

Ensuite, créons une classePlayerSorter pour créer notre collection et tentons de la trier en utilisantCollections.sort:

public static void main(String[] args) {
    List footballTeam = new ArrayList<>();
    Player player1 = new Player(59, "John", 20);
    Player player2 = new Player(67, "Roger", 22);
    Player player3 = new Player(45, "Steven", 24);
    footballTeam.add(player1);
    footballTeam.add(player2);
    footballTeam.add(player3);

    System.out.println("Before Sorting : " + footballTeam);
    Collections.sort(footballTeam);
    System.out.println("After Sorting : " + footballTeam);
}

Ici, comme prévu, il en résulte une erreur de compilation:

The method sort(List) in the type Collections
  is not applicable for the arguments (ArrayList)

Comprenons ce que nous avons fait de mal ici.

3. Comparable

Comme son nom l'indique,Comparable is an interface defining a strategy of comparing an object with other objects of the same type. This is called the class’s “natural ordering”.

En conséquence, afin de pouvoir trier - nous devons définir notre objetPlayer comme comparable en implémentant l'interfaceComparable:

public class Player implements Comparable {

    //...
    @Override
    public int compareTo(Player otherPlayer) {
        return (this.getRanking() - otherPlayer.getRanking());
    }
}

L'ordre de tri est décidé par la valeur de retour descompareTo() méthode.

La méthode renvoie un nombre indiquant si l'objet comparé est inférieur, égal ou supérieur à l'objet transmis en tant qu'argument.

Enfin, lorsque nous exécutons nosPlayerSorter maintenant, nous pouvons voir nosPlayers triés par leur classement:

Before Sorting : [John, Roger, Steven]
After Sorting : [Steven, John, Roger]

Maintenant que nous avons une compréhension claire de l’ordre naturel avecComparable, voyonshow we can use other types of ordering, in a more flexible manner que l’implémentation directe d’une interface.

4. Comparator

The Comparator interface defines a compare(arg1, arg2) method avec deux arguments qui représentent des objets comparés et fonctionne de manière similaire à la méthodeComparable.compareTo().

4.1. Création deComparators

Pour créer unComparator,, nous devons implémenter l'interfaceComparator.

Dans notre premier exemple, nous allons créer unComparator pour utiliser l'attributranking dePlayer pour trier les joueurs:

public class PlayerRankingComparator implements Comparator {

    @Override
    public int compare(Player firstPlayer, Player secondPlayer) {
       return (firstPlayer.getRanking() - secondPlayer.getRanking());
    }
}

De même, nous pouvons créer unComparator pour utiliser l'attributage dePlayer pour trier les joueurs:

public class PlayerAgeComparator implements Comparator {
    @Override
    public int compare(Player firstPlayer, Player secondPlayer) {
       return (firstPlayer.getAge() - secondPlayer.getAge());
    }
}

4.2. Comparators en action

Pour démontrer le concept, modifions nosPlayerSorter en introduisant un deuxième argument dans lesCollections.sort method qui est en fait l'instance deComparator que nous voulons utiliser.

Using this approach, we can override the natural ordering:

PlayerRankingComparator playerComparator = new PlayerRankingComparator();
Collections.sort(footballTeam, playerComparator);

Maintenant, exécutons nosPlayerRankingSorter to pour voir le résultat:

Before Sorting : [John, Roger, Steven]
After Sorting by ranking : [Steven, John, Roger]

Si nous voulons un ordre de tri différent, il suffit de changer lesComparator que nous utilisons:

PlayerAgeComparator playerComparator = new PlayerAgeComparator();
Collections.sort(footballTeam, playerComparator);

Maintenant, lorsque nous exécutons nosPlayerAgeSorter, nous pouvons voir un ordre de tri différent parage:

Before Sorting : [John, Roger, Steven]
After Sorting by age : [Roger, John, Steven]

4.3. Java 8Comparators

Java 8 fournit de nouvelles façons de définirComparators à l'aide d'expressions lambda et de la méthode de fabrique statiquecomparing().

Voyons un exemple rapide d'utilisation d'une expression lambda pour créer unComparator:

Comparator byRanking
 = (Player player1, Player player2) -> player1.getRanking() - player2.getRanking();

La méthodeComparator.comparing prend une méthode calculant la propriété qui sera utilisée pour comparer les éléments, et retourne une instanceComparator correspondante:

Comparator byRanking = Comparator
  .comparing(Player::getRanking);
Comparator byAge = Comparator
  .comparing(Player::getAge);

Vous pouvez explorer en profondeur les fonctionnalités de Java 8 dans notre guideJava 8 Comparator.comparing.

5. Comparator contreComparable

The Comparable interface is a good choice when used for defining the default ordering ou, en d’autres termes, si c’est le principal moyen de comparer des objets.

Ensuite, nous devons nous demander pourquoi utiliser unComparator si nous avons déjàComparable?

Il y a plusieurs raisons pour lesquelles:

  • Parfois, nous ne pouvons pas modifier le code source de la classe dont nous voulons trier les objets, rendant ainsi l’utilisation deComparableimpossible

  • L'utilisation deComparators nous permet d'éviter d'ajouter du code supplémentaire à nos classes de domaine

  • Nous pouvons définir plusieurs stratégies de comparaison différentes, ce qui n’est pas possible avecComparable

6. Conclusion

Dans ce didacticiel, nous avons exploré les interfacesComparable etComparator et discuté des différences entre elles.

Pour comprendre des sujets plus avancés de tri, consultez nos autres articles tels queJava 8 Comparator,Java 8 Comparison with Lambdas.

Et, comme d'habitude, le code source peut être trouvéover on Github.