Коли клас повинен бути порівнянним та / або порівняльним?


138

Я бачив класи, в яких реалізуються і Порівняння, і Порівняння . Що це означає? Навіщо мені використовувати один над іншим?


18
Ви читали на них javadoc? Це описує різні досить чітко.
скафман

1
Що є порівняльним та порівняльним і коли використовувати порівняльне та порівняльне. Щоб знати, прочитайте це посилання. це допоможе вам зрозуміти їх поведінку та використання. http://iandjava.blogspot.in/2012/10/comparable-and-comparator.html
RockStar

6
Це гарне запитання з хорошою, об'єктивною відповіддю. Мене страшно, що це закрито.
Рассел Сілва

3
Інші питання щодо StackOverflow стосуються цього як остаточного питання "У чому різниця між компаратором та порівнянним". Чому вона позначена як "неконструктивна"? Для Java-початківця це було дуже корисне питання!
Піт

Відповіді:


241

Наведений нижче текст походить від " Порівняння проти порівняльного"

Порівнюваний

Порівнюваний об'єкт здатний порівнювати себе з іншим об'єктом. Сам клас повинен реалізувати java.lang.Comparableінтерфейс, щоб мати можливість порівнювати його екземпляри.

Компаратор

Об'єкт порівняння здатний порівнювати два різні об'єкти. Клас не порівнює свої екземпляри, а деякі інстанції класу. Цей клас порівняння повинен реалізувати java.util.Comparatorінтерфейс.


для детального пояснення використання як компаратора, так і порівнянного: sysdotoutdotprint.com/index.php/2017/03/28/…
mel3kings

2
Ще одна добра стаття: codecramp.com/java-comparable-vs-comparator
EMM

@ mel3kings - Посилання недоступніше.
Гаурав

152

Реалізація Comparableозначає " я можу порівняти себе з іншим об'єктом ". Це зазвичай корисно, коли існує єдине природне порівняння за замовчуванням.

Реалізація Comparatorозначає " Я можу порівняти два інші об'єкти ". Це, як правило, корисно, коли існує декілька способів порівняння двох примірників типу - наприклад, ви можете порівняти людей за віком, іменем тощо.


1
Здравствуйте, Скейте, чи можете ви, будь ласка, кинути код за допомогою порівняльного та порівняльного.
Mdhar9e

5
@ mdhar9e: Прикладів багато - якщо вам важко перевести їх у свій конкретний сценарій, будь ласка, дайте більше інформації в новому запитанні.
Джон Скіт

2
@alireza: Я вже наводив приклад у другому абзаці: маючи різні компаратори, ви могли сортувати одну і ту ж колекцію (людей) за різними властивостями (вік, ім’я тощо). Ви не можете зробити це тільки шляхом Personреалізації Comparable, тому що ви не можете змінити , як порівнюються дві людини.
Джон Скіт

1
@feelgoodandprogramming: Ні, це різні алгоритми сортування . Тут потенційно є три фрагменти коду в трьох різних класах: 1) сама сутність, наприклад Person. 2) Порівняльник, наприклад, PersonAgeComparatorякий здатний порівняти дві різні сутності та вирішити, який повинен бути першим у цьому конкретному порядку сортування. 3) Код сортування, який бере колекцію сутностей і компаратор, і сортує цю колекцію за допомогою порівняльника для визначення порядку.
Джон Скіт

2
@RishiKeshPathak: Добре, що ти використовуєш Порівняння, якщо є лише одна очевидна річ для порівняння. І навіть тоді можна просто написати компаратор. Якщо у вас є дві різні програми, що використовують один клас, і одна хоче сортувати за віком, а інша за власним іменем, принаймні для однієї з них потрібно буде використовувати компаратор.
Джон Скіт

38

Порівняне дозволяє класу реалізувати власне порівняння:

  • це в одному класі (це часто є перевагою)
  • може бути лише одна реалізація (тому ви не можете використовувати це, якщо вам потрібні два різні випадки)

Для порівняння, компаратор - це зовнішнє порівняння:

  • зазвичай це в унікальному екземплярі (або в тому ж класі, або в іншому місці)
  • Ви називаєте кожну реалізацію способом сортування речей
  • ви можете надати компаратори для класів, які ви не контролюєте
  • реалізація може бути використана навіть у тому випадку, якщо перший об’єкт є нульовим

В обох реалізаціях ви все ще можете вибрати, з чим ви хочете порівнювати . За допомогою generics ви можете заявити про це і перевірити це під час компіляції. Це підвищує безпеку, але це також завдання визначити відповідне значення.

Як правило, я, як правило, використовую найзагальніший клас чи інтерфейс, з яким цей об'єкт можна порівняти, я передбачаю всі випадки використання ... Хоча не дуже точне визначення! :-(

  • Comparable<Object>дозволяє використовувати його у всіх кодах під час компіляції (що добре, якщо потрібно, або погано, якщо ні, і ви втрачаєте помилку часу компіляції); Ваша реалізація повинна справлятися з об'єктами та робити це за потребою, але надійно.
  • Comparable<Itself> дуже суворо навпаки.

Смішно, коли ви підкласируете себе до підкласу, підклас також повинен бути порівнянним і бути надійним щодо нього (або він би порушив Принцип Ліскова і призведе до помилок виконання).


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 зазвичай є помилкою. Їх безліч властивостей дуже важко передбачити, який порядок буде шукати найчастіше.
erickson

6

ось кілька відмінностей між компаратором та порівнянним, що я знайшов в Інтернеті:

  1. Якщо ви бачите, тоді логічною різницею між цими двома є компаратор порівняння в Java, порівняйте два надані йому об'єкти, тоді як порівняльний інтерфейс порівнює "це" посилання з вказаним об'єктом.

  2. Порівняльний в Java використовується для здійснення природного упорядкування об'єкта. У класах Java API String, Date та обгортка реалізують Порівнюваний інтерфейс.

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

  4. Об'єкти, що реалізують порівнянне в Java, можуть використовуватися як ключі в відсортованій карті або елементи в відсортованому наборі, наприклад, TreeSet, без зазначення будь-якого компаратора.

сайт: Як користуватися компаратором та порівнянним на Java? З прикладом

Детальніше: Як користуватися компаратором та порівнянним на Java? З прикладом


5

Comparableпризначений для об'єктів із природним упорядкуванням. Сам об’єкт знає, як його замовити.
Comparatorпризначений для об'єктів без природного замовлення або коли ви хочете використовувати інше замовлення.


4

Різниця між компараторським та порівнянним інтерфейсами

Comparable використовується для порівняння себе за допомогою іншого об’єкта.

Comparator використовується для порівняння двох типів даних є об'єктами.


2

Якщо ви бачите, то логічна різниця між цими двома полягає Comparatorв Java порівнянні двох наданих йому об'єктів, в той час як Comparableінтерфейс порівнює "це" посилання з вказаним об'єктом.

Comparableна Java використовується для здійснення природного упорядкування об'єкта. У Java API String, дати та обгорткові класи реалізують Comparableінтерфейс.

Якщо який - або клас реалізації Comparableінтерфейсу в Java , то збір цього об'єкта або Listабо Arrayможе бути відсортований автоматично, використовуючи Collections.sort()або Array.sort()метод і об'єкт буде відсортований на основі там природному порядку , визначеному compareToметодом.

Об'єкти, які реалізуються Comparableв Java, можуть використовуватися як ключі в відсортованій карті або елементи в сортованому наборі, наприклад TreeSet, без зазначення жодного Comparator.


0

Мій пояснювальний пояснювач для впровадження Порівняльного та Порівняльного:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.