В чем разница между compare () и compareTo ()?

110

В чем разница между Java compare()и compareTo()методами? Дают ли эти методы одинаковый ответ?

Попс
источник
1
Какой метод сравнения классов вы имеете в виду?
Маркус Лаусберг
для подробного объяснения использования функций compare () и compareTo (): sysdotoutdotprint.com/index.php/2017/03/28/…
mel3kings

Ответы:

160

Из JavaNotes :

  • a.compareTo(b):
    Сопоставимый интерфейс: сравнивает значения и возвращает int, который сообщает, если сравниваются значения меньше, равны или больше.
    Если объекты вашего класса имеют естественный порядок , реализуйте Comparable<T>интерфейс и определите этот метод. Все классы Java , которые имеют естественный порядок реализации Comparable<T>- Пример: String, обертки классов ,BigInteger

  • compare(a, b):
    Интерфейс компаратора: Сравнивает значения двух объектов. Это реализовано как часть Comparator<T>интерфейса, и обычно используется для определения одного или нескольких небольших служебных классов, реализующих это, для передачи таким методам, как sort()или для использования, путем сортировки структур данных, таких как TreeMapиTreeSet . Возможно, вы захотите создать объект Comparator для следующего:

    • Множественные сравнения . Чтобы предоставить несколько различных способов сортировки чего-либо. Например, вы можете захотеть отсортировать класс Person по имени, идентификатору, возрасту, росту ... Вы должны определить Comparator для каждого из них, чтобы передать его sort()методу.
    • Системный класс Для предоставления методов сравнения для классов, которые вы не можете контролировать. Например, вы можете определить компаратор для строк, который будет сравнивать их по длине.
    • Шаблон стратегии Для реализации шаблона стратегии, который представляет собой ситуацию, когда вы хотите представить алгоритм как объект, который вы можете передать в качестве параметра, сохранить в структуре данных и т. Д.

Если у ваших объектов класса один естественный порядок сортировки, вам может не понадобиться compare ().


Резюме из http://www.digizol.com/2008/07/java-sorting-comparator-vs-comparable.html

Сопоставимый Сопоставимый
объект может сравнивать себя с другим объектом.

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


Контексты использования:

Сопоставимый интерфейс

Метод equals ==и != операторы и проверяют на равенство / неравенство, но не предоставляют способ проверки относительных значений .
Некоторые классы (например, String и другие классы с естественным порядком) реализуют Comparable<T>интерфейс, который определяет compareTo()метод.
Вы захотите реализовать Comparable<T>в своем классе, если хотите использовать его с методами Collections.sort()или Arrays.sort().

Определение объекта Comparator

Вы можете создавать компараторы для произвольной сортировки для любого класса .
Например, Stringкласс определяет CASE_INSENSITIVE_ORDERкомпаратор .


Разница между этими двумя подходами может быть связана с понятием:
Упорядоченная коллекция :

Когда Коллекция упорядочена, это означает, что вы можете выполнять итерацию в коллекции в определенном (не случайном) порядке (а Hashtableне упорядочивается).

Коллекция с естественным порядком не просто упорядочивается, а сортируется . Определить естественный порядок может быть сложно! (как в естественном порядке строк ).


Еще одно отличие, отмеченное HaveAGuess в комментариях :

  • Comparable находится в реализации и не виден из интерфейса, поэтому, когда вы сортируете, вы действительно не знаете, что произойдет.
  • Comparator дает вам уверенность в том, что порядок будет четко определен.
VonC
источник
2
Поскольку этот ответ является исчерпывающим, вот кое-что, что меня раздражает в Comparable, вы можете добавить: он находится в реализации и не виден из интерфейса, поэтому, когда вы сортируете, вы действительно не знаете, что произойдет. Использование компаратора дает вам уверенность в том, что порядок будет четко определен
HaveAGuess
@HaveAGuess хороший момент. Я включил ваш комментарий в ответ для большей наглядности.
VonC
объекты имеют естественный порядок, что здесь означает естественный порядок? Имеет ли строковый элемент данных, например, имя в классе служащего естественный порядок ??
Нарендра Джагги
@NarendraJaggi См en.wikipedia.org/wiki/Enumeration . Порядок, облегчающий перечисление. «Естественный» в том смысле, что данный хороший порядок в наборе индексов обеспечивает уникальный способ перечислить следующий элемент с учетом частичного перечисления
VonC
2
@VedantKekan Спасибо. В этом ответе я восстановил 2 ссылки.
VonC
16

compareTo()это из Comparableинтерфейса.

compare()это из Comparatorинтерфейса.

Оба метода делают одно и то же, но каждый интерфейс используется в немного другом контексте.

Интерфейс Comparable используется для наложения естественного порядка на объекты реализующего класса. compareTo()Метод называется естественным методом сравнения. Интерфейс Comparator используется для полного упорядочения объектов реализующего класса. Для получения дополнительной информации см. Ссылки, где точно указано, когда использовать каждый интерфейс.

Юваль Адам
источник
Вы можете привести несколько примеров? Оба метода дают одинаковые ответы?
Я не знаю, почему «Сопоставимый» предназначен для естественного упорядочивания? Мы можем настроить это, не так ли?
c-an
14

Сходства:
оба являются пользовательскими способами сравнения двух объектов.
Оба возвращают intописание отношения между двумя объектами.

Различия: метод compare()- это метод, который вы обязаны реализовать, если реализуете Comparatorинтерфейс. Он позволяет передать два объекта в метод и возвращает intописание их отношений.

Comparator comp = new MyComparator();
int result = comp.compare(object1, object2);

Метод compareTo()- это метод, который вы обязаны реализовать, если реализуете Comparableинтерфейс. Это позволяет сравнивать объект с объектами аналогичного типа.

String s = "hi";
int result = s.compareTo("bye");

Резюме:
По сути, это два разных способа сравнения.

jjnguy
источник
9

Методы не обязательно должны давать одинаковые ответы. Это зависит от того, какие объекты / классы вы их называете.

Если вы реализуете свои собственные классы, которые, как вы знаете, хотите сравнить на каком-то этапе, вы можете попросить их реализовать интерфейс Comparable и соответственно реализовать метод compareTo ().

Если вы используете некоторые классы из API, которые не реализуют интерфейс Comparable, но вы все равно хотите их сравнить. Т.е. для сортировки. Вы можете создать свой собственный класс, который реализует интерфейс Comparator, и в его методе compare () вы реализуете логику.

Nicolai
источник
3

Сопоставимый интерфейс содержит вызываемый метод, compareTo(obj)который принимает только один аргумент и сравнивает себя с другим экземпляром или объектами того же класса.

Интерфейс компаратора содержит вызываемый метод, compare(obj1,obj2)который принимает два аргумента и сравнивает значения двух объектов из одного или разных классов.

Дилип Кумар
источник
3
compareTo(T object)

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

compare(T obj1, T obj2)

поступает из интерфейса java.util.Comparator, реализованного в отдельном классе, который сравнивает объекты другого класса, чтобы дать отрицательное значение int для первого объекта, меньшего, 0 для равного или положительного значения для большего, чем для второго объекта. Это необходимо, когда вы не можете заставить класс реализовать compareTo (), потому что он не может быть изменен. Он также используется, когда вам нужны разные способы сравнения объектов, а не только один (например, по имени или возрасту).

Godlovesdavid
источник
3

Используя Comparator, мы можем записать n логик сравнения для класса .

Например

Для автомобильного класса

У нас может быть класс Comparator для сравнения на основе номера модели автомобиля. У нас также может быть класс Comparator для сравнения в зависимости от года выпуска автомобиля.

Класс автомобиля

public class Car  {

    int modelNo;

    int modelYear;

    public int getModelNo() {
        return modelNo;
    }

    public void setModelNo(int modelNo) {
        this.modelNo = modelNo;
    }

    public int getModelYear() {
        return modelYear;
    }

    public void setModelYear(int modelYear) {
        this.modelYear = modelYear;
    }

}

Компаратор №1 на основе модели №

public class CarModelNoCompartor implements Comparator<Car>{

    public int compare(Car o1, Car o2) {

        return o1.getModelNo() - o2.getModelNo();
    }

}

Компаратор №2 в зависимости от модельного года

public class CarModelYearComparator implements Comparator<Car> {

    public int compare(Car o1, Car o2) {

        return o1.getModelYear() - o2.getModelYear();
    }

}

Но это невозможно в случае интерфейса Comparable .

В случае интерфейса Comparable у нас может быть только одна логика в методе compareTo () .

IamVickyAV
источник
2

Отношения между объектом, имеющим этот метод, и его участниками различаются.

compareTo()- это метод интерфейса Comparable , поэтому он используется для сравнения ЭТОГО экземпляра с другим.

compare()- это метод интерфейса Comparator , поэтому он используется для сравнения двух разных экземпляров другого класса друг с другом.

Если хотите, реализация Comparableозначает, что экземпляры класса можно легко сравнивать.
Реализация Comparatorозначает, что экземпляры подходят для сравнения разных объектов (других классов).

Ole
источник
2

Основное отличие заключается в использовании интерфейсов:

Comparable (который имеет compareTo ()) требует сравнения объектов (для использования TreeMap или сортировки списка) для реализации этого интерфейса. Но что, если класс не реализует Comparable, и вы не можете его изменить, потому что он является частью сторонней библиотеки? Затем вам нужно реализовать компаратор, который немного менее удобен в использовании.

Майкл Боргвардт
источник
2

compareTo()вызывается для одного объекта, чтобы сравнить его с другим объектом. compare()вызывается для некоторого объекта для сравнения двух других объектов.

Разница в том, где определяется логика, которая выполняет фактическое сравнение.

Abgan
источник
Не то, что я бы назвал фантастическим ответом, но я не думаю, что он заслуживает отрицательной оценки.
Пол Томблин,
Согласен, лично я оставляю за собой отрицательные голоса за неправильные или вводящие в заблуждение ответы. Это определенно верно.
Joachim Sauer
Так где же те «дружелюбные» люди, которые проголосовали против меня? Это мой второй правильный ответ, который был отклонен, потому что кто-то упустил суть. Либо вопрос отрицательного голосования, либо смысл моего ответа. Жизнь такая жестокая .. ;-)
Абган
0

Если вы хотите отсортировать список, который включает объект Foo, класс Foo должен реализовать интерфейс Comparable, потому что метод сортировки списка использует этот метод.

Если вы хотите написать класс Util, который сравнивает два других класса, вы можете реализовать класс Comparator.

Маркус Лаусберг
источник
0


Имя таблицы сотрудников , DoB, зарплата
Томас, 10.02.1982, 300
Даниэль, 11.03.1990, 400
Кваме, 10.02.1998, 520

Интерфейс Comparable позволяет вам сортировать список объектов, например сотрудников, по одному основному полю - например, вы можете сортировать по имени или по зарплате с помощью метода CompareTo ().

emp1.getName().compareTo(emp2.getName())

Более гибкий интерфейс для таких требований предоставляет интерфейс Comparator , единственный метод которого - compare ().

public interface Comparator<Employee> {
 int compare(Employee obj1, Employee obj2);
}

Образец кода

public class NameComparator implements Comparator<Employee> {

public int compare(Employee e1, Employee e2) {
     // some conditions here
        return e1.getName().compareTo(e2.getName()); // returns 1 since (T)omas > (D)an 
    return e1.getSalary().compareTo(e2.getSalary()); // returns -1 since 400 > 300
}

}

karto
источник
0

Еще один момент:

  • compareTo()из Comparableинтерфейса и compare()из Comparatorинтерфейса.
  • Comparableиспользуется для определения порядка по умолчанию для объектов внутри класса, в то время Comparatorкак используется для определения настраиваемого порядка, передаваемого методу.
Премрадж
источник
0

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

class Pokemon {
    int healthPoints;
    int attackDamage;
    public void battle (Comparable<Pokemon> comparable, Pokemon opponent) {
        if (comparable.compareTo(opponent) > 0) { //comparable needs to, but cannot, access this.healthPoints for example
            System.out.println("battle won");
        } else {
            System.out.println("battle lost");
        }
    }
}

comparableбудет лямбда или объект, и нет возможности comparableполучить доступ к полям thisPokemon. (В лямбда-выражении это thisотносится к экземпляру внешнего класса в области лямбда-выражения, как определено в тексте программы.) Так что это не работает , и мы должны использовать a Comparatorс двумя аргументами.

flow2k
источник
0

Используйте интерфейс Comparable для сортировки на основе более чем одного значения, такого как age, name, dept_name ... Для одного значения используйте интерфейс Comparator

Г. Браун
источник
-2
Important Answar
String name;
int roll;

public int compare(Object obj1,Object obj2) { // For Comparator interface
    return obj1.compareTo(obj1);
}

public int compareTo(Object obj1) { // For Comparable Interface
    return obj1.compareTo(obj);
}

Здесь в операторе return obj1.compareTo(obj1)or return obj1.compareTo(obj)принимают только Object; примитив не допускается. Например

name.compareTo(obj1.getName()) // Correct Statement.

Но

roll.compareTo(obj1.getRoll()) 
// Wrong Statement Compile Time Error Because roll 
// is not an Object Type, it is primitive type.

name - String Object, так что это сработало. Если вы хотите отсортировать количество учащихся, используйте приведенный ниже код.

public int compareTo(Object obj1) { // For Comparable Interface
    Student s = (Student) obj1;
    return rollno - s.getRollno();
}  

или

public int compare(Object obj1,Object obj2) { // For Comparator interface
    Student s1 = (Student) obj1;
    Student s2 = (Student) obj2;
    return s1.getRollno() - s2.getRollno();
}  
Бхабани Санкар Саху
источник