Есть ли в стандартном 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, и он делает это без такого класса, поэтому, когда этот код был написан, очевидным ответом было бы нет, но, возможно, он был добавлен позже.


person Yishai    schedule 13.07.2010    source источник
comment
Возможно, стоит упомянуть: ВНЕ стандартного API существует Guava's Ordering.natural ().   -  person Jon Onstott    schedule 26.08.2014


Ответы (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));
person Julien    schedule 04.11.2013
comment
Если вы еще не используете Java 8 и хотите использовать Comparator в чем-то простом, например Arrays.sort() или Collections.sort(), вы можете просто передать null аргументу Comparator, и он будет использовать естественный порядок. Однако не все виды использования Comparator гарантированно работают таким образом. По крайней мере, для Arrays и Collections так работает. - person Joe; 23.12.2014
comment
@Joe при использовании массивов класс элементов массива должен реализовывать интерфейс Comparable - person natinusala; 18.05.2017
comment
Comparator.<String>naturalOrder().compare(o1, o2) поддерживает буквенно-цифровые символы? - person Alex78191; 19.03.2019

Да, он определенно есть в JDK! Вот:

Collections.reverseOrder(Collections.reverseOrder())

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

person Kevin Bourrillion    schedule 13.07.2010
comment
Я не принимаю этот ответ, потому что он был преодолен Java 8, но это правильный ответ для pre-Java 8. Но на самом деле не используйте его ;-). - person Yishai; 21.01.2014
comment
Возможно, я упустил шутку. Почему бы мне на самом деле не использовать его (в более старой версии Java)? Здесь действительно ничего не меняется. Накладные расходы очень скромные. - person Jirka Hanika; 28.07.2014
comment
@JirkaHanika, Самое главное - в конечном итоге вы - можете сделать в кодировании, это сделать код понятным. Конечно, это дает хороший однострочник и использует только классы на основе API, но код в вопросе будет ясен и очевиден с первого взгляда для любого Java-разработчика среднего и более высокого уровня. Этот, как и любой другой трюк, запутает любого, кто придет и прочитает его позже. - person Yishai; 26.08.2014
comment
@Yishai - Хорошо, я понял вашу точку зрения, это, пожалуй, самый простой естественный компаратор в старом API, но я сам могу реализовать лучший с помощью API, столь же тривиально, используя compareTo. Спасибо. - person Jirka Hanika; 27.08.2014
comment
Comparator<String> reverseOrder = Collections.reverseOrder(); Comparator<String> naturalOrder = Collections.reverseOrder(reverseOrder); кажется мне достаточно понятным - person Antoine Snyers; 04.03.2016

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

person Eugene Ryzhikov    schedule 13.07.2010
comment
К вашему сведению, Гуава называет это Ordering.natural(). - person Kevin Bourrillion; 14.07.2010

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

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

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

Код 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));
  }
person Uri    schedule 13.07.2010
comment
кстати, в Java реализация Comparable называется Natural Ordering: filigris.com/products/docflex_javadoc/examples/new/java/lang/ - person Yishai; 14.07.2010
comment
@ Ишай: Ах. Я не знал об этом. Я бы предположил, что Java избегает такого термина, как огонь, потому что compareTo может иметь произвольный порядок, который может не соответствовать математическому естественному порядку или любому порядку в исходном домене. (например, порядок строк неестественен в том смысле, что это не чистый порядок естественного языка) - person Uri; 14.07.2010

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

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

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

person MAK    schedule 13.07.2010
comment
@downvoter: Пожалуйста, объясните причину отрицательного голоса. Вполне возможно, что я ошибся или ошибаюсь, но это не поможет, если я (или ОП) не знаю, что это такое. - person MAK; 14.07.2010
comment
MAK, хотя я не голосовал против, я не голосовал и за, потому что это уклоняется от вопроса. Иногда вам нужно, чтобы класс сортировался на основе шаблона стратегии (в моем случае это подсорт более крупной буквенно-цифровой сортировки), поэтому вам не нужен отдельный путь кода для естественного упорядочения (код TreeMap довольно уродливый из-за того, что они этого не сделали, хотя у них могли быть причины производительности для того, чтобы делать то, что они делали). - person Yishai; 14.07.2010
comment
Однако я определенно согласен с понижением голоса без комментариев. - person Yishai; 14.07.2010
comment
@Yishai: Точка взята. Итак, я говорю: нет, в классах Colections нет Comparator по умолчанию - по причинам, указанным в моем ответе. Вы должны свернуть свою собственную, если чувствуете в этом необходимость. - person MAK; 14.07.2010