Перейти к содержимому

Чем отличается comparable от comparator java

  • автор:

В чем разница между Comparable и Comparator?

Получается, это дублирующие друг друга вещи. Может, есть какие-то реальные различия?

Отслеживать

4,306 14 14 золотых знаков 42 42 серебряных знака 93 93 бронзовых знака

задан 14 мар 2017 в 0:41

5,327 11 11 золотых знаков 58 58 серебряных знаков 117 117 бронзовых знаков

Простыми словами — Comparable — сравниваемое, Comparator — сравнитель (то, что делает сравнение)

14 мар 2017 в 6:41

4 ответа 4

Сортировка: Сброс на вариант по умолчанию

  1. Comparator и Comparable — это оба интерфейсы
  2. Коллекция (ну хорошо, объект) является Comparable , когда объект может быть как то сравнен с другим объектом.
  3. Comparator , в отличие от этого — это способ сравнения объектов.

Пример: школьники на уроке физкультуры, физрук говорит: строиться по росту! — ученики быстренько сравнивают свои росты и строятся — кто выше вперед, кто ниже в хвост строя — это пример реализации Comparable , где в качестве compareTo(сосед) используется рост учеников.

Второй пример: те же школьники. Директор дает задание учителю математики сравнить учеников по успеваемости. Математичка берет журнал и сравнивает учеников по успеваемости — здесь работает compare(ученик1, ученик2) — Comparator’ом выступает математичка. Аналогично компаратором может выступить русичка или трудовик.

Отслеживать

34k 25 25 золотых знаков 130 130 серебряных знаков 222 222 бронзовых знака

Comparable и Comparator

Два новых интерфейса java.lang.Comparable и java.util.Comparator были добавлены в версии Java 5. Использование данных интерфейcов в своих приложениях позволяет упорядочивать (сортировать) данные.

Интерфейс Comparable

В интерфейсе Comparable объявлен только один метод compareTo (Object obj), предназначенный для упорядочивания объектов класса. Данный метод удобно использовать для сортировки списков или массивов объектов.

Метод compareTo (Object obj) сравнивает вызываемый объект с obj. В отличие от метода equals, который возвращает true или false, compareTo возвращает:

  • 0, если значения равны;
  • Отрицательное значение (обычно -1), если вызываемый объект меньше obj;
  • Положительное значение (обычно +1), если вызываемый объект больше obj.

Если типы объектов не совместимы при сравнении, то compareTo (Object obj) может вызвать исключение ClassCastException. Необходимо помнить, что аргумент метода compareTo имеет тип сравниваемого объекта класса.

Обычные классы Byte, Short, Integer, Long, Double, Float, Character, String уже реализуют интерфейс Comparable.

Пример реализации интерфейса Comparable
package test; import java.util.TreeSet; class Compare implements Comparable  < String str; int num; String TEMPLATE = "num = %d, str = '%s'"; Compare(String str, int num) < this.str = str; this.num = num; >@Override public int compareTo(Object obj) < Compare entry = (Compare) obj; int result = str.compareTo(entry.str); if(result != 0) return result; result = num - entry.num; if(result != 0) return (int) result / Math.abs( result ); return 0; >@Override public String toString() < return String.format(TEMPLATE, num, str); >> public class Example < public static void main(String[] args) < TreeSetdata = new TreeSet(); data.add(new Compare("Начальная школа" , 234)); data.add(new Compare("Начальная школа" , 132)); data.add(new Compare("Средняя школа" , 357)); data.add(new Compare("Высшая школа" , 246)); data.add(new Compare("Музыкальная школа", 789)); for (Compare e : data) System.out.println(e.toString()); > >

Результат выполнения программы:

num = 246, str = 'Высшая школа' num = 789, str = 'Музыкальная школа' num = 132, str = 'Начальная школа' num = 234, str = 'Начальная школа' num = 357, str = 'Средняя школа'

В примере значения сортируются сначала по полю str (по алфавиту), а затем по num в методе compareTo. Это хорошо видно по двум строкам с одинаковыми значения str и различными num. Чтобы изменить порядок сортировки значения str (в обратном порядке), необходимо внести небольшие изменения в метод compareTo.

@Override public int compareTo(Object obj) < int result = ((Comp)obj).str.compareTo(str); if(result != 0) return result; result = entry.number - number; if(result != 0) < return (int) result / Math.abs(result); return 0; >

Интерфейс Comparator : compare, compareTo

В интерфейсе Comparator объявлен метод compare (Object obj1, Object obj2), который позволяет сравнивать между собой два объекта. На выходе метод возвращает значение 0, если объекты равны, положительное значение или отрицательное значение, если объекты не тождественны.

Метод может вызвать исключение ClassCastException, если типы объектов не совместимы при сравнении. Простой пример реализации интерфейса Comparator:

package test; import java.util.TreeSet; import java.util.Iterator; import java.util.Comparator; class Compare implements Comparator  < @Override public int compare(String obj1, String obj2) < return obj1.compareTo(obj2); >> public class Example < public static void main(String[] args) < TreeSetdata = new TreeSet(); data.add(new String("Змей Горыныч" )); data.add(new String("Баба Яга" )); data.add(new String("Илья Муромец" )); data.add(new String("Алеша Попович" )); data.add(new String("Соловей Разбойник")); Iterator i = data.iterator(); while(i.hasNext()) System.out.println(i.next()); > >

Результат выполнения программы:

Алеша Попович Баба Яга Змей Горыныч Илья Муромец Соловей Разбойник

Усложним пример, и реализуем несколько видов сортировки. Для этого создадим класс Product с полями name, price и quantity.

class Product < private String name; private float price; private float quantity; public Product (String name, float price, float quantity) < this.name = name; this.price = price; this.quantity = quantity; >public String getName() < return name; >public void setName(String name) < this.name = name; >public float getPrice() < return price; >public void setPrice(float price) < this.price = price; >public float getQuantity() < return quantity; >public void setQuantity(float quantity) < this.quantity = quantity; >@Override public String toString() < return "Наименование '" + name + "', цена - " + String.valueOf (price) + ", количество - " + String.valueOf (quantity); >>

Создадим два класса (SortedByName, SortedByPrice), реализующих интерфейс Comparator для сортировки объектов по названию и по цене :

// сортировка по названию class SortedByName implements Comparator  < public int compare(Product obj1, Product obj2) < String str1 = obj1.getName(); String str2 = obj2.getName(); return str1.compareTo(str2); >> // сортировка по цене class SortedByPrice implements Comparator  < public int compare(Product obj1, Product obj2) < float price1 = obj1.getPrice(); float price2 = obj2.getPrice(); if (price1 >price2) < return 1; >else if (price1 < price2) < return -1; >else < return 0; >> >
Пример использования Arrays.sort :
public class Example < public static void main(String[] args) < Product[] products = new Product[3]; // заполним объект Product содержимым products[0] = new Product("Молоко", 35.56f,900.00f); products[1] = new Product("Кофе" ,199.50f, 90.00f); products[2] = new Product("Чай" , 78.50f,150.00f); // выведем данные без сортировки System.out.println("~~~~~ без сортировки"); for(Product product : products) System.out.println(product.toString()); // Сортировка по цене Arrays.sort(products, new SortedByPrice()); System.out.println("\n~~~ сортировка по цене"); for(Product product : products) System.out.println(product.toString()); // Сортировка по названию Arrays.sort(products, new SortedByName()); System.out.println("\n~~~ сортировка по названию"); for(Product product : products) System.out.println(product.toString()); >>

Результат выполнения программы:

~~~~~ без сортировки Наименование 'Молоко', цена - 35.56, количество - 900.0 Наименование 'Кофе', цена - 199.5, количество - 90.0 Наименование 'Чай', цена - 78.5, количество - 150.0 ~~~ сортировка по цене Наименование 'Молоко', цена - 35.56, количество - 900.0 Наименование 'Чай', цена - 78.5, количество - 150.0 Наименование 'Кофе', цена - 199.5, количество - 90.0 ~~~ сортировка по названию Наименование 'Кофе', цена - 199.5, количество - 90.0 Наименование 'Молоко', цена - 35.56, количество - 900.0 Наименование 'Чай', цена - 78.5, количество - 150.0

Для сортировки объектов были реализованы два независимых компаратора по наименованию и по цене (SortedByName и SortedByPrice). Сортировка выполняется с помощью класса Arrays, у которого есть метод sort. Данный метод в качестве второго аргумента принимает тип компаратора.

Arrays.sort(T[] arg1, Comparator arg2);

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

Collections.sort(List arg1, Comparator arg2);

Отличие интерфейсов Comparator и Comparable

Интерфейс Comparable используется только для сравнения объектов класса, в котором данный интерфейс реализован. Т.е. interface Comparable определяет логику сравнения объекта определенного ссылочного типа внутри своей реализации (по правилам разработчика).

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

Кофе-брейк #253. В чем различие между Comparable и Comparator. Что такое VarArgs (переменные аргументы) в Java

Java-университет

В чем различие между Comparable и Comparator в Java

Кофе-брейк #253. В чем различие между Comparable и Comparator. Что такое VarArgs (переменные аргументы) в Java - 1

Источник: Medium В этом руководстве объясняется, что такое интерфейсы Comparable и Comparator, и как их можно использовать для сортировки коллекций в Java.

Comparable

  1. Он должен возвращать целое положительное значение Positive(+ve) , если этот объект больше объекта сравнения.
  2. Он должен возвращать целое отрицательное значение Negative(-ve) , если этот объект меньше объекта сравнения.
  3. Он должен вернуть Zero(0) , если этот и сравниваемый объект равны.
 @Data @AllArgsConstructor @NoArgsConstructor public class Student implements Comparable < private Integer id; private String name; private String department; @Override public int compareTo(Student student) < return this.name.compareTo(student.name); >> 
 public class StudentComparableMain < public static void main(String[] args) < Student student=new Student(1,"John Doe","Java"); Student student2=new Student(2,"Jane Doe","Java"); Student student3=new Student(3,"Mike","Java"); Liststudents = Arrays.asList(student, student2,student3); System.out.println(students); Collections.sort(students); System.out.println(students); > > 

В приведенном выше примере кода первый оператор печати вернет список студентов в соответствии с порядком вставки.

 [Student(id=1, name=John Doe, department=Java), Student(id=2, name=Jane Doe, department=Java), Student(id=3, name=Mike, department=Java)] 

А второй оператор печати вернет список, отсортированный по именам студентов.

 [Student(id=2, name=Jane Doe, department=Java), Метод int compare(T var1, T var2) должен быть реализован пользовательским классом comparator. Student(id=1, name=John Doe, department=Java), Student(id=3, name=Mike, department=Java)] 

Comparator

  1. Он должен возвращать целое число положительное значение Positive(+ve) , если первый объект больше второго объекта.
  2. Он должен возвращать целое отрицательное значение Negative(-ve) , если первый объект меньше второго объекта.
  3. Он должен возвращать Zero(0) , если оба объекта равны.
 import java.util.Comparator; class StudentDeptComparator implements Comparator  < @Override public int compare(Student s1, Student s2) < return s1.getDepartment().compareTo(s2.getDepartment()); >> class StudentNameComparator implements Comparator  < @Override public int compare(Student s1, Student s2) < return s1.getName().compareTo(s2.getName()); >> 
 Student student=new Student(1,"Jane","Java"); Student student2=new Student(2,"John","React"); Student student3=new Student(3,"Mike","BA"); List students = Arrays.asList(student, student2,student3); // печатаем список согласно порядку вставки System.out.println(students); Collections.sort(students,new StudentDeptComparator()); // печатаем список, отсортированный по кафедрам студентов System.out.println(students); Collections.sort(students,new StudentNameComparator()); // печатаем список, отсортированный по именам студентов System.out.println(students); // сортируем список по имени и названию кафедры Collections.sort(students,new StudentNameComparator().thenComparing(new StudentDeptComparator())); System.out.println(students); 

В приведенном выше примере кода первый оператор печати вернет список студентов в соответствии с порядком вставки.

 [Student(id=1, name=Jane, department=Java), Student(id=2, name=John, department=React), Student(id=3, name=Mike, department=BA)] 

Второй оператор печати вернет список, отсортированный по кафедре студентов.

 [Student(id=3, name=Mike, department=BA), Student(id=1, name=Jane, department=Java), Student(id=2, name=John, department=React)] 

Третий оператор печати вернет список, отсортированный по именам студентов.

 [Student(id=1, name=Jane, department=Java), Student(id=2, name=John, department=React), Student(id=3, name=Mike, department=BA)] Student student=new Student(1,"Jane","Java"); Student student2=new Student(2,"Jane","BA"); Student student3=new Student(3,"Mike","BA"); Collections.sort(students,new StudentNameComparator() .thenComparing(new StudentDeptComparator())); System.out.println(students); 

Приведенный выше код сначала сортирует студентов по имени, а затем по кафедре. Результат оператора печати:

 [Student(id=2, name=Jane, department=BA), Student(id=1, name=Jane, department=Java), Student(id=3, name=Mike, department=BA)] 

Аналогично, Comparator также можно реализовать в лямбда-выражениях без использования какого-либо внешнего класса.

 Collections.sort( students, (s1,s2)-> < return s1.getDepartment().compareTo(s2.getDepartment()); >); 

С помощью Comparable мы можем сортировать нашу коллекцию только на основе одного атрибута, а с помощью Comparator мы можем обеспечить собственную сортировку на основе нескольких атрибутов.

Заключение

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

Что такое VarArgs (переменные аргументы) в Java

Источник: Medium Благодаря этой публикации вы сможете понять о способе работы с переменными аргументами (VarArgs) в Java. VarArgs (Variable Arguments) означает переменные аргументы. В Java мы можем передавать переменное количество аргументов одного типа в один и тот же метод. Это упрощает создание методов, которым необходимо принимать переменное количество аргументов. До выпуска JDK 5 мы не могли объявить метод с переменным количеством аргументов. Аргументы переменной длины можно было обрабатывать либо с помощью перегруженных методов, либо путем передачи массива методу. Они оба часто приводят к ошибкам, и ухудшают читаемость кода. Чтобы решить эту проблему, в JDK 5 были введены переменные аргументы (Var Args). Переменный аргумент — это функция Java, которая позволяет нам передавать переменное количество аргументов одному методу. Но есть одно ограничение — они должны быть одного типа. VarArgs реализуется с использованием многоточия ( «. » ) в объявлении метода.

 Public void myMethod(int. number) < //body >

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

 public class VarargsExample < public static void printNumbers(int. numbers) < System.out.println("Number of arguments: " + numbers.length); for (int num : numbers) < System.out.print(num + " "); >System.out.println(); > public static void main(String[] args) < printNumbers(); // Вывод: Количество аргументов: 0 printNumbers(1, 2, 3); // Вывод: Количество аргументов: 3 1 2 3 printNumbers(10, 20); // Вывод: Количество аргументов: 2 10 20 >> 

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

 Int myMethod(int a, float b, double. c) < //Body >
  • VarArgs также можно перегружать, но перегрузка может привести к неоднозначности.
  • В методе может быть только один переменный аргумент.
  • VarArgs должны быть последним аргументом.

Чем отличается Comparator от Comparable?

Интерфейс Comparable определяет естественный порядок среди объектов. Java Collections Framework активно использует этот порядок. По нему упорядочены элементы SortedSet / SortedMap , им упорядочиваются элементы списков и массивов в методе sort().

Порядок определяется единственным методом compareTo . Отрицательный результат означает что текущий объект «меньше» чем переданный параметром, 0 – равен, положительный – больше. Рекомендуется чтобы равные с точки зрения equals объекты всегда были равны с точки зрения compareTo .

С математической точки зрения это должен быть линейный порядок. Он требует выполнения четырех свойств:
1. Антирефлексивность: x.compareTo(x) всегда 0 ;
2. Антисимметричность: если x.compareTo(y) > 0 , то y.compareTo(x) < 0 ;
3. Транзитивность: если x.compareTo(y) > 0 и y.compareTo(z) > 0 , то x.compareTo(z) > 0 ;
4. Полнота: отношение определено для любых объектов класса (кроме null ).

Интерфейс Comparator – это логика Comparable, вынесенная в отдельный объект. Компаратор реализует паттерн Стратегия. Большинство платформенных методов, использующих Comparable имеют перегруженный вариант с не-comparable объектом и внешним компаратором.

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

Кроме основного метода compare() , в компараторе есть набор утилитарных методов для комбинирования и модификации компараторов. Все они возвращают новый компаратор, позволяя сделать его иммутабельным.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *