Когда должен быть класс Comparable и / или Comparator?

141

Я видел классы, которые реализуют как Comparable, так и Comparator . Что это значит? Почему я должен использовать одно вместо другого?

Ник Хайнер
источник
18
Вы читали о них javadoc? Он довольно ясно описывает различное.
skaffman
1
Что такое сопоставимый и компаратор, и когда использовать сопоставимый и компаратор. Чтобы узнать об этом, прочтите эту ссылку. это поможет вам понять их поведение и использование. http://iandjava.blogspot.in/2012/10/comparable-and-comparator.html
RockStar
6
Это хороший вопрос с хорошим объективным ответом. Я встревожен тем, что он закрыт.
Рассел Сильва
3
Другие вопросы по StackOverflow называют это окончательным вопросом «В чем разница между компаратором и сопоставимым». Почему помечено как «неконструктивно»? Как новичок в Java, это был очень полезный вопрос!
Пит

Ответы:

242

Текст ниже взят из Comparator vs Comparable

Сопоставимый

Сравнимый объект может сравнивать себя с другим объектом. Сам класс должен реализовывать java.lang.Comparableинтерфейс, чтобы иметь возможность сравнивать его экземпляры.

Компаратор

Объект-компаратор может сравнивать два разных объекта. Класс сравнивает не свои экземпляры, а экземпляры некоторых других классов. Этот класс компаратора должен реализовывать java.util.Comparatorинтерфейс.

Дэн
источник
для подробного объяснения использования как Comparator, так и сопоставимых: sysdotoutdotprint.com/index.php/2017/03/28/…
mel3kings
2
Еще одна хорошая статья: codecramp.com/java-comparable-vs-comparator
EMM
@ mel3kings - Ссылка больше недоступна.
Gaurav
156

Реализация Comparableозначает « Я могу сравнить себя с другим объектом ». Обычно это полезно, когда есть единственное естественное сравнение по умолчанию.

Реализация Comparatorозначает « Я могу сравнить два других объекта». Это обычно полезно, когда есть несколько способов сравнения двух экземпляров типа - например, вы можете сравнивать людей по возрасту, имени и т. Д.

Джон Скит
источник
1
Привет, скит, не могли бы вы сбросить код, используя сопоставимый и компаратор.
Mdhar9e
5
@ mdhar9e: Примеров много - если вам сложно перевести их в свой конкретный сценарий, дайте больше информации в новом вопросе.
Джон Скит
2
@alireza: я уже приводил пример во втором абзаце: имея разные компараторы, вы можете сортировать одну и ту же коллекцию (людей) по разным свойствам (возраст, имя и т. д.). Вы не можете сделать это, просто создав Personорудие Comparable, потому что тогда вы не сможете изменить способ сравнения двух людей.
Джон Скит,
1
@feelgoodandprogramming: Нет, это разные алгоритмы сортировки . Здесь потенциально есть три фрагмента кода трех разных классов: 1) Сама сущность, например Person. 2) Компаратор, например, PersonAgeComparatorкоторый может сравнивать два разных объекта и решать, что должно быть первым в этом конкретном порядке сортировки. 3) Код сортировки, который принимает набор сущностей и компаратор и сортирует эту коллекцию, используя компаратор для определения порядка.
Джон Скит,
2
@RishiKeshPathak: Ну, это больше, если вы используете Comparable, если есть только одна очевидная вещь для сравнения. И даже тогда вы можете просто написать компаратор. Если у вас есть две разные программы, использующие один и тот же класс, и одна хочет сортировать только по возрасту, а другая - по имени, по крайней мере одна из них должна будет использовать компаратор.
Джон Скит
38

Comparable позволяет классу реализовывать собственное сравнение:

  • он из того же класса (часто это преимущество)
  • может быть только одна реализация (поэтому вы не можете использовать ее, если хотите два разных случая)

Для сравнения, Comparator - это внешнее сравнение:

  • обычно он находится в уникальном экземпляре (либо в том же классе, либо в другом месте)
  • вы называете каждую реализацию так, как вы хотите сортировать вещи
  • вы можете предоставить компараторы для классов, которые вы не контролируете
  • реализация может использоваться, даже если первый объект имеет значение NULL

В обеих реализациях вы по-прежнему можете выбирать, с чем вы хотите сравнивать . С помощью дженериков вы можете объявить это и проверить это во время компиляции. Это повышает безопасность, но также сложно определить подходящее значение.

В качестве ориентира я обычно использую самый общий класс или интерфейс, с которым можно было бы сравнить этот объект, во всех возможных вариантах использования ... Хотя не очень точное определение! :-(

  • Comparable<Object>позволяет использовать его во всех кодах во время компиляции (что хорошо, если необходимо, или плохо, если нет, и вы теряете ошибку времени компиляции); ваша реализация должна справляться с объектами и приводиться по мере необходимости, но надежно.
  • Comparable<Itself> очень строгий наоборот.

Забавно, когда вы подклассифицируете себя к подклассу, подкласс также должен быть сопоставимым и быть устойчивым к нему (или это нарушит принцип Лискова и даст вам ошибки во время выполнения).

KLE
источник
20

java.lang.Comparable

  1. Чтобы реализовать Comparableинтерфейс, класс должен реализовывать единственный методcompareTo()

    int a.compareTo(b)

  2. Вы должны изменить класс, экземпляр которого вы хотите отсортировать. Таким образом, для каждого класса может быть создана только одна последовательность сортировки.

java.util.Comparator

  1. Чтобы реализовать интерфейс Comparator, класс должен реализовывать единственный метод compare()

    int compare (a,b)

  2. Вы создаете класс отдельно от класса, экземпляр которого вы хотите отсортировать. Так что для каждого класса можно создать несколько последовательностей сортировки.
кодиак
источник
14

Comparable предназначен для обеспечения порядка по умолчанию для объектов данных, например, если объекты данных имеют естественный порядок.

A Comparatorпредставляет собой заказ для конкретного использования.

звездно-голубой
источник
8

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

Некоторые классы действительно предусматривают Comparatorsобщие случаи; например, Strings по умолчанию чувствительны к регистру при сортировке, но есть также статический Comparatorвызов CASE_INSENSITIVE_ORDER.

Майкл Майерс
источник
7
Я не уверен, что согласен с предпочтением Comparable. Некоторые объекты обладают сильным чувством естественного порядка, а именно числа во всех их формах: натуральные числа, действительные числа, даты и т. Д. Но даже другие относительно примитивные объекты, такие как символьные строки, не имеют универсального применимого порядка. В случае более сложных объектов, таких как сущность из модели предметной области приложения, реализация Comparable обычно является ошибкой. Из-за их множества свойств слишком сложно предугадать, какой порядок будет требоваться чаще всего.
erickson
6

Вот несколько различий между Comparator и Comparable, которые я нашел в Интернете:

  1. Если вы видите, то логическая разница между этими двумя: Comparator в Java сравнивает два предоставленных ему объекта, в то время как интерфейс Comparable сравнивает «эту» ссылку с указанным объектом.

  2. Comparable в Java используется для реализации естественного упорядочивания объектов. В Java API String, Date и классы оболочки реализуют интерфейс Comparable.

  3. Если какой-либо класс реализует интерфейс Comparable в Java, тогда коллекция этого объекта List или Array может быть автоматически отсортирована с помощью метода Collections.sort () или Array.sort (), и объект будет отсортирован на основе естественного порядка, определенного методом CompareTo.

  4. Объекты, которые реализуют Comparable в Java, могут использоваться как ключи в отсортированной карте или элементы в отсортированном наборе, например TreeSet, без указания какого-либо Comparator.

сайт: Как использовать Comparator и Comparable в Java? С примером

Подробнее: Как использовать Comparator и Comparable в Java? С примером

javapassion
источник
5

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

Майкл Ллойд Ли млк
источник
4

Разница между интерфейсами Comparator и Comparable

Comparable используется для сравнения себя с другим объектом.

Comparator используется для сравнения двух типов данных - объектов.

SravaniChowdary.Gorijavolu
источник
2

Если вы видите, то логическая разница между этими двумя заключается Comparatorв том, что в Java сравниваются два предоставленных ему объекта, а Comparableинтерфейс сравнивает «эту» ссылку с указанным объектом.

Comparableв Java используется для реализации естественного упорядочивания объекта. В Java API String, Date и классы оболочки реализуют Comparableинтерфейс.

Если какой - либо класс реализации Comparableинтерфейса в Java , то сбор этого объекта либо Listили Arrayможет быть отсортирован автоматически, используя Collections.sort()или Array.sort()метод и объект будет отсортирован на основе там естественном порядке , определенном compareToметодом.

Объекты, которые реализованы Comparableв Java, могут использоваться как ключи в отсортированной карте или элементы в отсортированном наборе, например TreeSet, без указания каких-либо Comparator.

Шринивас
источник
0

Моя аннотационная библиотека для реализации Comparable и Comparator:

public class Person implements Comparable<Person> {         
    private String firstName;  
    private String lastName;         
    private int age;         
    private char gentle;         

    @Override         
    @CompaProperties({ @CompaProperty(property = "lastName"),              
        @CompaProperty(property = "age",  order = Order.DSC) })           
    public int compareTo(Person person) {                 
        return Compamatic.doComparasion(this, person);         
    }  
} 

Щелкните ссылку, чтобы увидеть больше примеров. компаматичный

Цзяньминь Лю
источник
3
Добро пожаловать в stackoverflow. Это старый вопрос, и на него уже был дан ответ. Как правило, лучше не восстанавливать устаревшие темы, если ваш ответ не содержит чего-то существенно нового или отличного от предыдущих.
Oers