Pourquoi Java Comparable
utilisé? Pourquoi quelqu’un implémenterait-il Comparable
dans une classe? Quel est un exemple réel où vous devez mettre en œuvre comparable?
Voici un exemple de vie réelle. Notez que Ssortingng
implémente également Comparable
.
class Author implements Comparable{ Ssortingng firstName; Ssortingng lastName; @Override public int compareTo(Author other){ // compareTo should return < 0 if this is supposed to be // less than other, > 0 if this is supposed to be greater than // other and 0 if they are supposed to be equal int last = this.lastName.compareTo(other.lastName); return last == 0 ? this.firstName.compareTo(other.firstName) : last; } }
plus tard..
/** * List the authors. Sort them by name so it will look good. */ public List listAuthors(){ List authors = readAuthorsFromFileOrSomething(); Collections.sort(authors); return authors; } /** * List unique authors. Sort them by name so it will look good. */ public SortedSet listUniqueAuthors(){ List authors = readAuthorsFromFileOrSomething(); return new TreeSet (authors); }
Comparable définit un ordre naturel. Cela signifie que vous le définissez lorsqu’un object doit être considéré comme “inférieur à” ou “supérieur à”.
Supposons que vous ayez un tas d’entiers et que vous voulez les sortinger. C’est assez simple, il suffit de les placer dans une collection sortingée, non?
TreeSet m = new TreeSet (); m.add(1); m.add(3); m.add(2); for (Integer i : m) ... // values will be sorted
Mais maintenant, supposons que j’ai un object personnalisé, où le sorting a du sens pour moi, mais n’est pas défini. Disons que j’ai des données représentant les dissortingcts par code postal avec la densité de population, et je veux les classer par densité:
public class Dissortingct { Ssortingng zipcode; Double populationDensity; }
Maintenant, le moyen le plus simple de les sortinger est de les définir avec un ordre naturel en implémentant Comparable, ce qui signifie que ces objects sont définis de manière standard:
public class Dissortingct implements Comparable{ Ssortingng zipcode; Double populationDensity; public int compareTo(Dissortingct other) { return populationDensity.compareTo(other.populationDensity); } }
Notez que vous pouvez faire la même chose en définissant un comparateur. La différence est que le comparateur définit la logique de classement en dehors de l’object . Peut-être que dans un processus séparé, je dois commander les mêmes objects par code postal – dans ce cas, le classement n’est pas nécessairement une propriété de l’object ou diffère de l’ordre naturel des objects. Vous pouvez utiliser un comparateur externe pour définir un ordre personnalisé sur des nombres entiers, par exemple en les sortingant par leur valeur alphabétique.
Fondamentalement, la logique de commande doit exister quelque part. Cela peut être –
dans l’object lui-même, s’il est naturellement comparable (étend les entiers Comparable -eg)
fourni dans un comparateur externe, comme dans l’exemple ci-dessus.
Cité du javadoc
Cette interface impose un ordre total sur les objects de chaque classe qui l’implémente. Cet ordre est appelé ordre naturel de la classe et la méthode compareTo de la classe est appelée méthode de comparaison naturelle.
Les listes (et les tableaux) d’objects qui implémentent cette interface peuvent être sortingées automatiquement par Collections.sort (et Arrays.sort). Les objects qui implémentent cette interface peuvent être utilisés comme clés dans une carte sortingée ou comme éléments dans un ensemble sortingé, sans qu’il soit nécessaire de spécifier un comparateur.
Edit: ..et fait le bit important en gras.
Le fait qu’une classe implémente Comparable
signifie que vous pouvez prendre deux objects de cette classe et les comparer. Certaines classes, comme certaines collections (fonction de sorting dans une collection) qui maintiennent les objects dans l’ordre, les considèrent comme comparables (pour sortinger, il faut savoir quel object est le plus grand, etc.).
La plupart des exemples ci-dessus montrent comment réutiliser un object comparable existant dans la fonction compareTo. Si vous souhaitez implémenter votre propre compareTo lorsque vous souhaitez comparer deux objects de la même classe, par exemple un object AirlineTicket que vous souhaitez sortinger par prix (moins est classé en premier), suivi du nombre d’escales (encore une fois, less est classé en premier), vous feriez ce qui suit:
class AirlineTicket implements Comparable { public double cost; public int stopovers; public AirlineTicket(double cost, int stopovers) { this.cost = cost; this.stopovers = stopovers ; } public int compareTo(Cost o) { if(this.cost != o.cost) return Double.compare(this.cost, o.cost); //sorting in ascending order. if(this.stopovers != o.stopovers) return this.stopovers - o.stopovers; //again, ascending but swap the two if you want descending return 0; } }
Un moyen facile de mettre en œuvre plusieurs comparaisons de champs est avec Guava’s ComparisonChain – alors vous pouvez dire
public int compareTo(Foo that) { return ComparisonChain.start() .compare(lastName, that.lastName) .compare(firstName, that.firstName) .compare(zipCode, that.zipCode) .result(); }
au lieu de
public int compareTo(Person other) { int cmp = lastName.compareTo(other.lastName); if (cmp != 0) { return cmp; } cmp = firstName.compareTo(other.firstName); if (cmp != 0) { return cmp; } return Integer.compare(zipCode, other.zipCode); } }
Par exemple, lorsque vous souhaitez avoir une collection ou une carte sortingée
Comparable est utilisé pour comparer les instances de votre classe. Nous pouvons comparer des instances de plusieurs façons, c’est pourquoi nous devons implémenter une méthode compareTo
afin de savoir comment (atsortingbuts) nous voulons comparer des instances.
Dog
: package test; import java.util.Arrays; public class Main { public static void main(Ssortingng[] args) { Dog d1 = new Dog("brutus"); Dog d2 = new Dog("medor"); Dog d3 = new Dog("ara"); Dog[] dogs = new Dog[3]; dogs[0] = d1; dogs[1] = d2; dogs[2] = d3; for (int i = 0; i < 3; i++) { System.out.println(dogs[i].getName()); } /** * Output: * brutus * medor * ara */ Arrays.sort(dogs, Dog.NameComparator); for (int i = 0; i < 3; i++) { System.out.println(dogs[i].getName()); } /** * Output: * ara * medor * brutus */ } }
Main
: package test; import java.util.Arrays; public class Main { public static void main(Ssortingng[] args) { Dog d1 = new Dog("brutus"); Dog d2 = new Dog("medor"); Dog d3 = new Dog("ara"); Dog[] dogs = new Dog[3]; dogs[0] = d1; dogs[1] = d2; dogs[2] = d3; for (int i = 0; i < 3; i++) { System.out.println(dogs[i].getName()); } /** * Output: * brutus * medor * ara */ Arrays.sort(dogs, Dog.NameComparator); for (int i = 0; i < 3; i++) { System.out.println(dogs[i].getName()); } /** * Output: * ara * medor * brutus */ } }
Voici un bon exemple d'utilisation de comparable en Java:
http://www.onjava.com/pub/a/onjava/2003/03/12/java_comp.html?page=2
Lorsque vous implémentez une interface Comparable
, vous devez implémenter la méthode compareTo()
. Vous en avez besoin pour comparer des objects, afin d’utiliser, par exemple, la méthode de sorting de la classe ArrayList
. Vous avez besoin d’un moyen de comparer vos objects pour pouvoir les sortinger. Vous avez donc besoin d’une méthode compareTo()
personnalisée dans votre classe pour pouvoir l’utiliser avec la méthode de sorting ArrayList
. La méthode compareTo()
renvoie -1,0,1.
Je viens de lire un chapitre correspondant dans Java Head 2.0, j’apprends encore.
OK, mais pourquoi ne pas simplement définir une méthode compareTo()
sans implémenter une interface comparable. Par exemple une classe City
définie par son name
et sa temperature
et
public int compareTo(City theOther) { if (this.temperature < theOther.temperature) return -1; else if (this.temperature > theOther.temperature) return 1; else return 0; }