Существует ли естественный компаратор в стандартном api?


Мне нужен компаратор как часть паттерна стратегии, который может использовать либо естественный порядок объектов, либо некоторый пользовательский порядок. Для случая естественного упорядочения я написал простой компаратор:

private static class NaturalComparator<T extends Comparable<? super T>> implements Comparator<T> {
    @Override
    public int compare(T o1, T o2) {
        return o1.compareTo(o2);
    }
}

Кажется достаточно простым, но мне было интересно, знает ли кто-нибудь о нем в стандартном API. Я посмотрел на TreeMap, и он делает это без такого класса, поэтому, когда этот код был написан, очевидный ответ был бы нет, но, возможно, он был добавлен позже.

5 47

5 ответов:

Добавлено в компаратор на Java 8:

static <T extends Comparable<? super T>> Comparator<T> naturalOrder()

Используйте его так, например:

Comparator<Double> natural = Comparator.<Double>naturalOrder();
return natural.compare(1.0, 1.1));

Да, JDK определенно имеет его! Вот ОНО:

Collections.reverseOrder(Collections.reverseOrder())

Просто шучу. (Но это правда. (Просто на самом деле не используйте это. (Всегда.)))

JDK не имеет его, однако он называется ComparableComparator и существует во многих фреймворках, таких как Spring, Apache Commons, Hibernate и многие другие

Я не знаком с компаратором по умолчанию в Java, но очевидно, что компаратор для compareTo часто является простой оболочкой.

В стандартном API нет общего понятия "естественный порядок", хотя некоторые встроенные типы, такие как числа, имеют реализацию compareTo, которая затем становится их естественным порядком.

TreeMap и TreeSet и все это должно вызвать исключение RuntimeException, если объект, который вы вставляете, не реализует сопоставимое. Таким образом, например, вы могли бы бросить в строки или числа, но не другая коллекция.

Код TreeMap не использует компаратор, если он недоступен - вместо него используется compareTo. Чтобы использовать compareTo, он выполняет приведение к Comparable, которое является источником исключений.

    private int compare(K k1, K k2) {
      return (comparator==null ? ((Comparable <K>)k1).compareTo(k2)
                                : comparator.compare((K)k1, (K)k2));
  }

Я думаю, что если класс имеет естественный порядок, то в Java для него более привычно реализовывать Comparable, а не иметь реализацию Comparator для каждого класса.

Таким образом, если рассматриваемые объекты имеют определенный естественный порядок, они должны реализовать Comparable и иметь определенный метод compareTo. Нет необходимости искать Comparator. Большинство классов на java.util принимает либо необязательный Comparator, Если есть какой-либо конкретный порядок, который должен быть наложен, либо просто пытается вызвать compareTo на объекты, если нет другой заказ указан.

Итак, короче говоря: реализуйте Comparable всякий раз, когда вы хотите наложить естественный порядок на класс, используйте только Comparator, Когда вы хотите что-то другое, чем естественный порядок.