Maison >Java >javaDidacticiel >Comment fonctionne Comparateur en Java ?
Parfois, lorsque vous travaillez sur un projet, il est nécessaire de trier un certain type de collection d'objets, pour cela vous pensez peut-être qu'il est nécessaire d'implémenter nos propres algorithmes de tri, mais cela est quelque peu inutile, même si cela ne fait pas de mal de savoir comment ils fonctionnent. Par exemple, si vous disposez d'un tableau d'entiers, vous pouvez utiliser la méthode Arrays.sort() qui accepte un tableau de primitives et le trie par ordre croissant, en profitant du fait qu'il n'est pas nécessaire d'attribuer le résultat à un tableau d'entiers. nouvelle variable, puisque la méthode modifie le tableau d'origine.
int[] numbers = {9, 8, 5, 3, 1, 2, 4, 6, 7}; Arrays.sort(numbers); System.out.println(Arrays.toString(numbers)); // Output [1, 2, 3, 4, 5, 6, 7, 8, 9]
Cela s'applique également lorsque vous avez une collection d'objets personnalisés, par exemple un enregistrement de type Movie, mais si nous voyons la méthode Arrays.sort() elle n'accepte pas un tableau d'objets de ce type, elle doit donc faut-il utiliser la méthode sort() qui accepte comme paramètres un objet de type T et un objet de type Comparator super T> qui est une interface fonctionnelle. Cette interface est très importante, car de nombreuses autres méthodes Java l'utilisent pour comparer des objets de manière personnalisée. Par exemple, la méthode Collections.sort() ou la méthode sort() d'un objet List, même Streams accepte un Comparator pour trier les éléments.
L'interface fonctionnelle Comparator (étant fonctionnelle elle peut être écrite comme une expression lambda) est une interface qui permet de comparer deux objets de type T, elle est donc utilisée pour comparer des entiers, des chaînes, des objets, etc. L'interface dispose de plusieurs méthodes statiques et par défaut, mais l'important est la méthode compare(), qui est celle qui doit être implémentée pour comparer deux objets. compare() reçoit deux objets de type T et renvoie un entier. La signature de la méthode est la suivante :
int compare(T o1, T o2);
Cette méthode renvoie un nombre négatif si o1 est inférieur à o2, zéro s'ils sont égaux et un nombre positif si o1 est supérieur à o2, normalement elle renvoie -1, 0 ou 1 respectivement.
Analysons ce que renvoie la méthode compare() puisque l'ordre des objets en dépend. Il est important de considérer que la signification de ce que renvoie la méthode est relative, c'est-à-dire si vous souhaitez trier par ordre croissant ou décroissant. Cela dépend de la situation et de la manière dont elle est mise en œuvre. Considérons le enregistrement suivant pour chaque exemple :
int[] numbers = {9, 8, 5, 3, 1, 2, 4, 6, 7}; Arrays.sort(numbers); System.out.println(Arrays.toString(numbers)); // Output [1, 2, 3, 4, 5, 6, 7, 8, 9]
int compare(T o1, T o2);
public record Movie( String name, List<String> actors, int budget, int year ) { }
// a < b -> -1 a.year() < b.year() -> -1
Supposons que nous ayons les films suivants dans un objet de type List
// a > b -> 1 a.budget() > b.budget() -> 1
Si vous souhaitez classer les films par année de sortie par ordre croissant, vous pouvez créer un objet de type Comparateur
// a == b -> 0 a.actors().size() == b.actors().size() -> 0
Il peut également être implémenté en tant que classe anonyme dans la méthode sort() :
Movie movie1 = new Movie("The Godfather", Arrays.asList("Marlon Brando", "Al Pacino"), 6000000, 1972); Movie movie2 = new Movie("The Godfather: Part II", Arrays.asList("Al Pacino", "Robert De Niro"), 13000000, 1974); Movie movie3 = new Movie("The Shawshank Redemption", Arrays.asList("Tim Robbins", "Morgan Freeman"), 25000000, 1994); Movie movie4 = new Movie("The Dark Knight", Arrays.asList("Christian Bale", "Heath Ledger"), 185000000, 2008); List<Movie> movies = Arrays.asList(movie1, movie2, movie3, movie4);
Ou de manière plus concise en utilisant une expression lambda directement dans la méthode sort() :
Comparator<Movie> comparatorByYear = new Comparator<Movie>() { @Override public int compare(Movie o1, Movie o2) { return o1.year() - o2.year(); } }; movies.sort(comparatorByYear);
N'importe laquelle de ces implémentations triera la liste par ordre croissant par année de sortie. Si vous souhaitez trier par ordre décroissant, vous pouvez changer l'ordre des arguments dans l'expression lambda, ou ajouter un signe négatif dans la soustraction :
movies.sort(new Comparator<Movie>() { @Override public int compare(Movie o1, Movie o2) { return o1.year() - o2.year(); } });
Quelques autres exemples de la manière dont une liste d'objets personnalisés peut être triée :
movies.sort((p1, p2) -> p1.year() - p2.year());
movies.sort((p1, p2) -> p2.year() - p1.year()); // o movies.sort((p1, p2) -> - (p1.year() - p2.year()));
movies.sort((p1, p2) -> p1.actors().size() - p2.actors().size());
Entre autres exemples, on peut avoir le cas où il faut trier une liste d'entiers par ordre décroissant,
movies.sort((p1, p2) -> p2.budget() - p1.budget()); // o movies.sort((p1, p2) -> - (p1.budget() - p2.budget()));
Pour ce faire, vous pouvez également utiliser la méthode statique Comparator.reverseOrder() qui renvoie un comparateur qui classe les éléments par ordre décroissant et Comparator.naturalOrder() qui classe les éléments par ordre croissant.
int[] numbers = {9, 8, 5, 3, 1, 2, 4, 6, 7}; Arrays.sort(numbers); System.out.println(Arrays.toString(numbers)); // Output [1, 2, 3, 4, 5, 6, 7, 8, 9]
Au sein de Java, il existe déjà des méthodes qui nous permettent d'effectuer ce type de comparaisons de manière efficace, par exemple Integer.compare() qui compare deux entiers et renvoie un nombre négatif si le premier argument est inférieur au second, zéro if sont égaux et un nombre positif si le premier argument est supérieur au second. Si nous analysons le fonctionnement de cette méthode, nous pouvons voir qu'elle est similaire à ce qui a été expliqué ci-dessus et renvoie exactement ce que nécessite la méthode compare() de l'interface Comparator. L'implémentation de Integer.compare() est la suivante :
int compare(T o1, T o2);
Donc, si vous souhaitez trier les films par année de sortie par ordre croissant, vous pouvez utiliser Integer.compare() :
public record Movie( String name, List<String> actors, int budget, int year ) { }
Parfois, les méthodes de référence peuvent être utilisées pour effectuer des comparaisons différemment qu'auparavant, par exemple pour trier une liste d'entiers par ordre croissant :
// a < b -> -1 a.year() < b.year() -> -1
Integer n'est pas la seule classe à avoir une méthode compareTo(), par exemple String a une méthode compareTo() qui compare deux chaînes lexicographiquement, elle peut donc être utilisée pour trier une liste de chaînes, ou même utiliser CharSequence avec son Méthode compare() (représente techniquement une séquence de caractères).
// a > b -> 1 a.budget() > b.budget() -> 1
Reprenons l'exemple des films, si vous souhaitez trier les films par année de sortie par ordre croissant, vous pouvez utiliser la méthode comparantInt() comme méthode de référence :
// a == b -> 0 a.actors().size() == b.actors().size() -> 0
Ou pour comparer selon un attribut de type String, en l'occurrence le nom du film :
Movie movie1 = new Movie("The Godfather", Arrays.asList("Marlon Brando", "Al Pacino"), 6000000, 1972); Movie movie2 = new Movie("The Godfather: Part II", Arrays.asList("Al Pacino", "Robert De Niro"), 13000000, 1974); Movie movie3 = new Movie("The Shawshank Redemption", Arrays.asList("Tim Robbins", "Morgan Freeman"), 25000000, 1994); Movie movie4 = new Movie("The Dark Knight", Arrays.asList("Christian Bale", "Heath Ledger"), 185000000, 2008); List<Movie> movies = Arrays.asList(movie1, movie2, movie3, movie4);
Parfois, vous devrez peut-être trier une liste d'objets selon plusieurs attributs. Par exemple, si vous souhaitez trier les films par année de sortie par ordre croissant et par budget par ordre décroissant, vous pouvez utiliser la méthode thenComparing() qui reçoit un comparateur et est responsable du classement par plusieurs attributs. Par exemple, s'il y a deux films a et b, avec la même année de sortie, ils seront classés par budget.
Comparator<Movie> comparatorByYear = new Comparator<Movie>() { @Override public int compare(Movie o1, Movie o2) { return o1.year() - o2.year(); } }; movies.sort(comparatorByYear);
Les comparateurs sont utiles en Java à de nombreuses reprises, car ils vous permettent de comparer des objets de manière personnalisée, et pas seulement cela, mais ils peuvent également être utilisés dans de nombreuses méthodes de collecte Java, et même avoir plus d'un comparateur à trier de différentes manières. Quoi qu'il en soit, vous pouvez consulter la documentation de Comparator dans l'EDI ou dans la documentation officielle de Java pour voir quelles méthodes peuvent être utilisées et comment elles peuvent être implémentées.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!