Comparator — Нужна помощь с Java

Содержание

Интерфейс Comparator

В прошлом уроке мы рассмотрели как сравнивать объекты классов, реализующих интерфейс Comparable.

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

Интерфейс содержит метод int compare(T o1, T o2) , который должен быть реализован классом, реализующим компаратор.

Метод compare возвращает числовое значение — если оно отрицательное, то объект o1 предшествует объекту o2 , иначе — наоборот. А если метод возвращает ноль, то объекты равны.

Для применения интерфейса нам вначале надо создать класс компаратора, который реализует этот параметризованный интерфейс.

Рассмотрим пример использования интерфейса Comparator :

Тоже самое перепишем с использованием метода comparing() интерфейса Comparator :

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

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

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

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

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

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

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

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

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

Пример использования Arrays.sort :

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

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

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

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

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

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

Пример сортировки объектов Java (Comparable и Comparator)

В этом руководстве показано использование java.lang.Comparable и java.util.Comparator для сортировки объекта Java на основе значения его свойства.

1. Сортировать массив

Чтобы отсортировать массив, используйте Arrays.sort () .

2. Сортировать ArrayList

Чтобы отсортировать ArrayList, используйте Collections.sort () .

3. Сортировать объект с сопоставимым

Как насчет Java-объекта? Давайте создадим класс Fruit:

Чтобы отсортировать его, вы можете снова подумать о Arrays.sort () , см. Пример ниже:

Хорошая попытка, но что вы ожидаете от Arrays.sort () ? Вы даже не упомянули, что сортировать в классе Fruit. Таким образом, он получит следующую ошибку:

Чтобы отсортировать объект по его свойству, необходимо, чтобы объект реализовал интерфейс Comparable и переопределил метод compareTo () . Давайте снова увидим новый класс Fruit.

Новый класс Fruit реализовал интерфейс Comparable и переопределил метод compareTo () для сравнения его количественного свойства в порядке возрастания.

Метод CompareTo () сложно объяснить при целочисленной сортировке, просто запомните

  1. this.quantity – CompareQuantity – это возрастающий порядок.
  2. CompareQuantity – this.quantity в порядке убывания.
Цукерберг рекомендует:  Html разработка - JS в вёрстке

Чтобы узнать больше о методе compareTo (), прочитайте эту сравнительную документацию .

Запустите его снова, теперь массив Fruits сортируется по количеству в порядке возрастания.

4. Сортировать объект с помощью компаратора

Как насчет сортировки с помощью Fruit’s «FruitName» или «Количество»? Интерфейс Comparable позволяет сортировать только одно свойство. Для сортировки с несколькими свойствами вам нужен Comparator . Смотрите новый обновленный класс Fruit снова:

Класс Fruit содержит статический метод FruitNameComparator для сравнения «fruitName». Теперь объект Fruit может сортироваться по свойству «количество» или «fruitName». Запустите это снова.

1. Сортируйте массив Fruit по его свойству «fruitName» в порядке возрастания.

2. Сортируйте массив Fruit по его количеству в порядке возрастания.

Java.lang.Comparable и java.util.Comparator являются мощными, но требуют времени, чтобы понять и использовать их, возможно, это связано с отсутствием подробного примера.

Мои мысли…

В будущем класс Arrays должен обеспечить более общий и удобный метод – Arrays.sort (Object, String, flag) .

Сортировать массив объектов по его «fruitName» в порядке возрастания.

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

Comparator

Язык Java /

Основы языка Java

24 мая 2013 15:20
24 мая 2013 15:26
24 мая 2013 15:29
24 мая 2013 16:04

означает, что вы описываете анонимный класс, который имплементирует интерфейс Comparator.

24 мая 2013 19:31

Почитайте про анонимные классы.
Quote:

TreeSet set1 = new TreeSet (
new Comparator () <
public int compare(String s1, String s2)
>
);

означает, что вы описываете анонимный класс, который имплементирует интерфейс Comparator.

24 мая 2013 19:45
24 мая 2013 19:50
24 мая 2013 19:56

Анонимные классы (anonymous inner classes)

Анонимные классы являются важным подспорьем в повседневной жизни Java-программистов. Анонимный класс (anonymous class) — это локальный класс без имени.

Классический пример анонимного класса:

На основании анонимного класса создается поток и запускается с помощью метода start класса Thread. Синтаксис создания анонимного класса базируется на использовании оператора new с именем класса (интерфейса) и телом новосозданного анонимного класса.

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

Читайте и гуглите дальше сами. )

24 мая 2013 19:59

Анонимные классы (anonymous inner classes)

Анонимные классы являются важным подспорьем в повседневной жизни Java-программистов. Анонимный класс (anonymous class) — это локальный класс без имени.

Классический пример анонимного класса:

new Thread(new Runnable() <
public void run() <
.
>
>).start();

На основании анонимного класса создается поток и запускается с помощью метода start класса Thread. Синтаксис создания анонимного класса базируется на использовании оператора new с именем класса (интерфейса) и телом новосозданного анонимного класса.

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

Читайте и гуглите дальше сами. )

Спасибо, а то я как то упустил, что анонимные интерфейсы тоже бывают)

Изменен:24 мая 2013 15:00
27 мая 2013 16:10

Анонимные классы (anonymous inner classes)

Анонимные классы являются важным подспорьем в повседневной жизни Java-программистов. Анонимный класс (anonymous class) — это локальный класс без имени.

Классический пример анонимного класса:

new Thread(new Runnable() <
public void run() <
.
>
>).start();

На основании анонимного класса создается поток и запускается с помощью метода start класса Thread. Синтаксис создания анонимного класса базируется на использовании оператора new с именем класса (интерфейса) и телом новосозданного анонимного класса.

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

Читайте и гуглите дальше сами. )

Спасибо, а то я как то упустил, что анонимные интерфейсы тоже бывают)

Анонимных интерфейсов не бывает. Еще раз, запись
new Thread(new Runnable() <
public void run() <
.
>
>).start();

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

Очень смущен выводом типа компаратора Java 8

я смотрел на разницу между Collections.sort и list.sort , в частности с помощью Comparator статические методы и требуются ли типы param в лямбда-выражениях. Прежде чем мы начнем, я знаю, что могу использовать ссылки на методы, например Song::getTitle чтобы преодолеть мои проблемы, но мой запрос здесь не столько то, что я хочу исправить, но то, что я хочу получить ответ, т. е. почему компилятор Java обрабатывает его таким образом.

это моя находка. Предположим, мы есть ArrayList типа Song , С некоторыми добавленными песнями, есть 3 стандартных метода get:

вот вызов обоих типов метода сортировки, который работает, без проблем:

как только я начну цеплять thenComparing происходит следующее:

т. е. синтаксические ошибки, потому что он не знает типа

4 ответов

во-первых, все примеры, которые вы говорите, вызывают ошибки компиляции с эталонной реализацией (javac из JDK 8.) Они также отлично работают в IntelliJ, поэтому вполне возможно, что ошибки, которые вы видите, специфичны для Eclipse.

ваш основной вопрос: «почему он перестает работать, когда я начинаю цепляться.»Причина в том, что в то время как лямбда-выражения и общие вызовы методов Поли выражения (их тип зависит от контекста), когда они появляются в качестве параметров метода, когда они появляются вместо выражений приемника метода, они не являются.

когда вы говорите

существует достаточно информации о типе, чтобы решить для обоих аргументов типа comparing() и тип аргумента p1 . The comparing() call получает свой целевой тип из подписи Collections.sort , поэтому comparing() должен возвратить Comparator , и поэтому p1 должно быть Song .

но когда вы начинаете цепь:

теперь у нас есть проблема. Мы знаем, что составное выражение comparing(. ).thenComparing(. ) имеет целевой тип Comparator , но потому что выражение приемника для цепочки, comparing(p -> p.getTitle()) , является общим вызовом метода, и мы не можем вывести его параметры типа из его других аргументов, нам не повезло. Поскольку мы не знаем тип этого выражения, мы не знаем, что оно имеет thenComparing метод и т. д.

есть несколько способов, чтобы исправить это, все включите ввод дополнительной информации о типе, чтобы исходный объект в цепочке мог быть правильно набран. Вот они, в грубом порядке уменьшения желательности и увеличения навязчивости:—20

  • используйте точную ссылку на метод (без перегрузок), например Song::getTitle . Затем это дает достаточно информации о типе, чтобы вывести переменные типа для comparing() вызовите, и поэтому дайте ему тип, и поэтому продолжайте вниз по цепочке.
  • используйте явную лямбду (как вы сделали в своем примере).
  • предоставьте свидетеля типа для comparing() звоните: Comparator. comparing(. ) .
  • предоставьте явный целевой тип с приведением, приведя выражение приемника к Comparator .

проблема заключается в выводе типа. Без добавления (Song s) к первому сравнению, comparator.comparing не знает тип ввода, поэтому по умолчанию используется Object.

вы можете исправить эту проблему 1 из 3 способов:

используйте новый ссылочный синтаксис метода Java 8

вытащите каждый шаг сравнения в локальную ссылку

редактировать

принуждение тип, возвращаемый компаратором (обратите внимание, что вам нужен как тип ввода, так и тип ключа сравнения)

Я думаю, что «последний» thenComparing синтаксическая ошибка вводит вас в заблуждение. На самом деле это проблема типа со всей цепочкой, это просто компилятор, отмечающий только конец цепочки как синтаксическую ошибку, потому что именно тогда окончательный тип возврата не соответствует, Я думаю.

Я не уверен, почему List делает лучшую работу по выведению, чем Collection поскольку должен делать тот же тип захвата, но, по-видимому, нет.

playlist1.sort(. ) создает границу песни для переменной типа E, из объявления playlist1, которая» рябит » в компаратор.

на Collections.sort(. ) , такой границы нет, и вывод из типа первого компаратора недостаточно для компилятора, чтобы вывести остальное.

Я думаю, вы получите «правильное» поведение от Collections. sort(. ) , но у вас нет установки java 8, чтобы проверить ее для вас.

другой способ справиться с этой ошибкой времени компиляции:

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

Нужна помощь Понимание внутренней работы компаратора интерфейса в Java

Я пытаюсь понять теорию позади интерфейс Comparator в Java. В частности, мне нужна помощь, чтобы понять, как возвращаемое значение метода сравнения () определяет, что происходит в верхней части списка.

Java код

Вывод

обсуждение

Глядя на IncreasedComparison классе, если сравнивать метод возвращает отрицательное значение, то это означает , что нижние ключи (и соответствующие элементы) находятся в верхней части списка. Затем , глядя на DecreasedComparison классе, когда сравнить метод возвращает положительное значение, тем выше ключи (и соответствующие элементы) находятся в верхней части списка.

Почему это происходит? Где это происходит, в которых разница в ключевых значениях может диктовать ли элемент TreeList находится в верхней части списка в одном случае, но это может быть на дне в следующем?

Происходит это , когда объект , реализующий интерфейс Comparator передается в конструктор TreeMap? Поставив его в конструктор, делает это установить прецедент в рамках TreeMap , что отрицательное возвращаемое значение compare() метода означает , что меньшие значения Integer должны быть в верхней части списка , и наоборот для положительных значений , возвращаемых в compare() методе?

Интерфейсы Comparable и Comparator в Java

Привет! Это статья про интерфейсы Comparable и Comparator. Для понимания материала Вам, естественно, нужно знать что такое интерфейс.

Что такое Comparable и Comparator в Java

В своей работе программисты часто сталкиваются с тем, что надо что-то сортировать — например, покупая товары в интернет-магазине Вы можете сортировать их по цене, популярности и т.д.

Но для того, чтобы что-то отсортировать, нам нужно сравнивать объекты по каким-то правилам. Тут, казалось бы, все просто — мы можем сортировать числа, да и в сортировке по алфавиту нет ничего сложного. Да, с такими данными все легко. Но как нам сравнить два объекта класса Car? По цене, пробегу, лошадиным силам или дате выпуска? А может по количеству владельцев?

Если у нас есть два объекта класса Cat — как сравнить их? По кличке? По породе? По возрасту?

Как видите, не всегда очевидно как именно можно сравнить два объекта. Но не беда — мы сами можем прописать эти правила. Именно для этого мы можем реализовать интерфейсы Comparable и Comparator.

  • Кроме того, некоторые встроенные возможности в Java можно использовать только, если Ваш класс реализует Comparable или Comparator.

Интерфейс Comparable

С английского «Comparable» переводится как «сравнимый». Имплементируя этот интерфейс мы как бы говорим «Эй, теперь объекты этого класса можно сравнивать между собой! И я знаю, как это сделать!» А до этого было нельзя ��

Так как выглядит интерфейс Comparable? Очень просто — в нем находится всего один метод:

Как сделать этот код с помощью Comparator?

Извините, я давно не работаю с Java. У меня есть класс, который сортирует тип int, и я пытаюсь сделать это, но это не компилируется:

Я хотел бы отсортировать вектор int, используя этот метод, используя компаратор для сортировки в порядке возрастания.

Пример кода довольно неполон, но для начала вы не можете привести Object к int. использование

Прежде всего, не используйте Vector или Hashtable в этом отношении, они оба считаются deprecated для всех практических целей. Используйте реализации List или Map .

Вместо этого используйте List , это современный и правильный способ манипулировать списком Integer как объектами.

Если вы хотите использовать другой Comparator то вы можете использовать:

Так как Integer реализует Comparable , по умолчанию он будет сортировать List в порядке возрастания. Целое число для деталей.

Это правильный, идиоматический способ сортировки классов List и Collection в современной Java. Все остальное показывает, что вы не понимаете язык и то, что он предоставляет.

Нужна помощь Понимание внутренних работ интерфейса Comparator в Java

4 A.Sharma [2015-04-21 07:19:00]

Я пытаюсь понять теорию интерфейса Comparator в Java. В частности, мне нужна помощь в понимании того, как возвращаемое значение метода compare() определяет, что находится в верхней части списка.

Код Java

Выход

Обсуждение

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

Почему это происходит? Где это происходит, когда разница в значениях ключа может определять, находится ли элемент TreeList в верхней части списка в одном случае, но тогда он может быть внизу в следующем?

Это происходит, когда объект, реализующий интерфейс Comparator, передается в конструктор TreeMap? Поместив его в конструктор, устанавливает ли он прецедент в TreeMap, что отрицательное возвращаемое значение метода compare() означает, что меньшие значения Integer должны быть в верхней части списка и наоборот для положительных значений возврата compare() метод?

3 ответа

Что означают результаты

Один из способов думать о результатах java.util.Comparator.compareTo заключается в следующем. Пусть

Где ? может быть = или > или . Затем добавим нуль к уравнению

Затем некоторую алгебру переместить ? в другую позицию

Если мы попытаемся поместить различные возможные значения для ? на основе значений a и b , мы имеем следующие три комбинации

То, где вы получаете положительные, отрицательные и нулевые значения целых чисел.

Зачем проходить эти результаты?

Для целых чисел логика compareTo будет немного тупой, поскольку вы можете просто сказать a > b , но для других непростых типов, таких как String , это имеет больше смысла.

Представьте себе мир без метода a compareTo . Это означало бы, что нам нужно было бы реализовать по крайней мере два метода для сравнения: a isGreaterThan и equals . Просто этих двух было бы достаточно, потому что меньше, чем было бы

Однако, если все это вызовет много вызовов методов, когда compareTo сохранит намного больше вызовов в конечном итоге.

Волшебный мир Java

четверг, 2 февраля 2012 г.

Сортировка и упорядочивание. Интерфейсы Comparable и Comparator

25 комментариев:

>Основным отличием интерфейса Comparator от >Comparable является то, что вы можете создавать >несколько видов независимых сортировок.

Ничто не мешает создать несколько видов независимых сортировок и с помощью Comparable.
А реальное отличие — в том что Comparator в отличие от Comparable можно использовать для сравнения final объектов сторонних библиотек по позволяющих заимплементить Comparable.

Согласен. Моя формулировка не совсем правильная.

А как создать несколько видов сортировок с помощью Comparable? Можно пример?

опечатался:
по позволяющих -> не позволяющих

Очень ценная поправка

у меня почему-то подчеркивает компаратор в этой строке:
Arrays.sort(p, new SortedByPrice());

С чем может быть связано?

Вообще странно. Проверил, пример рабочий. Какую ошибку выдает?
Что было изменено? Можно код.

Зачем в этих строках использовать приведение:

public int compare(Product obj1, Product obj2) <

String str1 = ((Product) obj1).getName();
String str2 = ((Product) obj2).getName();

И так передаются аргументы типа продакт. Чего я не понимаю?

В данном случае, согласен, это лишнее. Автоматом написал. Но если бы аргументы были Object вместо Product, то приведение было бы нужно.
Спасибо, за то, что указали.

Большое спасибо, все очень доступно и понятно.

Еще б добавить: javadoc: The ordering imposed by a comparator c on a set of elements S is sa >И то же самое Comparable

Объясните пожалуйста, после того как мы переписали метод compareTo, как здесь public class Example <

Цукерберг рекомендует:  Курс по бд - Задача к собеседованию написать SQL-запрос
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих