web-dev-qa-db-fra.com

Existe-t-il un comparateur naturel dans l'API standard?

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.

54
Yishai

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));
63
Julien

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.)))

50
Kevin Bourrillion

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

10
Eugene Ryzhikov

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.

2
MAK

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));
  }
2
Uri