J'ai besoin d'un comparateur dans le cadre d'un modèle de stratégie qui peut utiliser l'ordre naturel des objets ou un ordre personnalisé. Pour le cas de commande naturel, j'ai écrit un comparateur simple:
private static class NaturalComparator<T extends Comparable<? super T>> implements Comparator<T> {
@Override
public int compare(T o1, T o2) {
return o1.compareTo(o2);
}
}
Cela semble assez simple, mais je me demandais si quelqu'un en connaissait un dans l'API standard. J'ai regardé TreeMap, et il le fait sans une telle classe, donc quand ce code a été écrit, la réponse apparente serait non, mais peut-être qu'il a été ajouté plus tard.
Ajouté à Comparateur dans Java 8 :
static <T extends Comparable<? super T>> Comparator<T> naturalOrder()
Utilisez-le comme ceci, par exemple:
Comparator<Double> natural = Comparator.<Double>naturalOrder();
return natural.compare(1.0, 1.1));
Oui, le JDK l'a définitivement! C'est ici:
Collections.reverseOrder(Collections.reverseOrder())
Je rigole. (Mais c'est vrai. (Ne l'utilisez pas vraiment. (Jamais.)))
JDK ne l'a pas, mais il est appelé ComparableComparator et il existe dans de nombreux frameworks tels que Spring , Apache Commons , Hibernate et bien d'autres
Je pense que si une classe a un ordre naturel, il est plus courant dans Java pour qu'elle implémente Comparable
plutôt que d'avoir une implémentation Comparator
pour chaque classe.
Ainsi, si les objets en question ont un ordre naturel défini, ils doivent implémenter Comparable
et avoir la méthode compareTo
définie. Pas besoin d'aller chercher un Comparator
. La plupart des classes de Java.util prennent soit un Comparator
facultatif s'il y a un ordre spécifique à imposer, soit essayent simplement d'appeler compareTo
sur les objets si aucun autre ordre n'est spécifié.
Donc, pour faire court: implémentez Comparable
chaque fois que vous souhaitez imposer un ordre naturel à une classe, utilisez uniquement un Comparator
lorsque vous voulez autre chose que l'ordre naturel.
Je ne suis pas familier avec un comparateur par défaut en Java, mais évidemment, Comparator to compareTo est souvent un simple wrapper.
Il n'y a pas de général d'ordre naturel dans l'API standard, bien que certains types intégrés, comme les nombres, aient une implémentation de compareTo qui devient alors leur ordre naturel.
TreeMap
et TreeSet
et tout cela devrait lever une RuntimeException si l'objet que vous insérez n'implémente pas Comparable. Ainsi, par exemple, vous pouvez ajouter des chaînes ou des nombres mais pas une autre collection.
Le code de TreeMap
n'utilise pas de comparateur s'il n'est pas disponible - il utilise à la place compareTo
. Pour utiliser compareTo
, il effectue un transtypage en Comparable
, qui est la source des exceptions.
private int compare(K k1, K k2) {
return (comparator==null ? ((Comparable <K>)k1).compareTo(k2)
: comparator.compare((K)k1, (K)k2));
}