Для чего служат интерфейсы comparable и 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 возвращает:

Если типы объектов не совместимы при сравнении, то 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 позволяет создавать объекты, которые будут управлять процессом сравнения (например при сортировках).

Источник

Выбор между Comparator и Comparable

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

В java эти правила определяются на уровне классов, к которым принадлежат объекты. Для примера возьмем класс для описания счета пользователя:

В зависимости от контекста сравнение счетов пользователя может происходить по разным правилам, например:

в приложении пользователь видит счета, отсортированные по currency, потом по value;

в админке счета всех пользователей отсортированы по дате изменения.

Для реализации сравнения на больше-меньше в java предусмотрено две возможности:

UserAccount реализует интерфейс Comparable В этом случае два объекта получают возможность сравнения между собой: acc1.compareTo(acc2)

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

Согласно документации использование Comparable возможно, если для сравнения используется естественный порядок (class’s natural ordering). По ссылке есть представление разработчиков, что такое естественный порядок для стандартных классов (String, Date). Мне не удалось выяснить, что такое естественный порядок в общем случае. Выглядит, что это интуитивное представление разработчика о порядке в данном контексте. При этом даже для стандартных классов порядок может быть не интуитивен (в каком порядке должны идти значения BigDecimal с разной точностью, например 4.0 и 4.00?). Практика показывает, что «естественность» правил различается в понимании разных разработчиков и контекстов. Для меня необходимость опоры на интуицию является аргументом против использования Comparable.

При написании кода приходится лавировать между явностью и неявностью. Явность хороша тем, что для понимания участка кода требуется рассмотреть лишь узкий контекст его использования. В то же время неявность позволяет использовать одинаковые правила для всех участков кода. Разберем на примере: разработчику требуется отсортировать список счетов. Правила сравнения можно указать:

явно: Arrays.sort(accountsList, accountByValueComparator)

В случае явной передачи компаратора найти его использования элементарно. Я считаю это аргументом за использование компаратора. (Еще одним примером сложностей с поиском неявных использований может служить equals/hashCode, но альтернативы в виде «Equalator»-а для них нет).

Источник

Компаратор и сопоставимый в Java

Краткое и практическое руководство по интерфейсам сравнения и компаратора.

1. введение

Сравнения в Java довольно просты – пока это не так.

2. Настройка примера

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

Мы начнем с создания простого Игрок класс:

Затем давайте создадим класс Player Sorter для создания вашей коллекции и попытаемся отсортировать ее с помощью Collections.сортировка :

Здесь, как и ожидалось, это приводит к ошибке во время компиляции:

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

3. Сопоставимые

Как следует из названия, Comparable – это интерфейс, определяющий стратегию сравнения объекта с другими объектами того же типа. Это называется “естественным упорядочением”класса.

Соответственно, чтобы иметь возможность сортировать – мы должны определить наш объект Player как сопоставимый, реализовав интерфейс Comparable :

Метод возвращает число, указывающее, является ли сравниваемый объект меньше, равен или больше объекта, передаваемого в качестве аргумента.

4. Компаратор

4.1. Создание Компараторов

4.2. Компараторы в действии

Используя этот подход, мы можем переопределить естественный порядок :

Теперь давайте запустим наш PlayerRankingSorter, чтобы увидеть результат:

4.3. Компараторы Java 8

Java 8 предоставляет новые способы определения Компараторов с помощью лямбда-выражений и сравнения() статического заводского метода.

Давайте рассмотрим краткий пример того, как использовать лямбда-выражение для создания компаратора :

Метод Comparator.comparing принимает метод, вычисляющий свойство, которое будет использоваться для сравнения элементов, и возвращает соответствующий экземпляр Comparator :

Вы можете подробно изучить функциональность Java 8 в нашем руководстве по сравнению Java 8 Comparator.

5. Компаратор против сопоставимого

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

Есть несколько причин, по которым:

6. Избегайте трюка с вычитанием

В ходе этого урока мы использовали метод Integer.compare() для сравнения двух целых чисел. Можно возразить, что вместо этого мы должны использовать этот умный однострочный:

Хотя он намного более лаконичен по сравнению с другими решениями, он может стать жертвой переполнения целых чисел в Java :

Следовательно, несмотря на то, что мы ожидали, “Джон” стоит перед “Роджером” в отсортированной коллекции:

7. Заключение

В этом уроке мы изучили интерфейсы Comparable и Comparator и обсудили различия между ними.

Источник

Русские Блоги

Разница между Comparable и Comparator в Java

1. Введение в сопоставимый

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

Кроме того, объекты, которые реализуют этот интерфейс, могут использоваться как ключи в упорядоченной карте или как коллекции в упорядоченной коллекции без указания компаратора. Интерфейс определяется следующим образом:

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

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

Теперь мы предполагаем класс Person, код которого выглядит следующим образом:

Теперь, когда есть два объекта класса Person, как мы можем сравнить их размер? Мы можем реализовать интерфейс Comparable, позволив Person:

2. Введение в Компаратор

Теперь, если вышеупомянутый класс Person не реализует интерфейс Comparable, как следует сравнивать размер? Мы можем создать новый класс и позволить ему реализовать интерфейс Comparator для создания «компаратора».

Теперь мы можем использовать этот компаратор для сортировки:

В-третьих, разница между Comparable и Comparator

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

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

Интеллектуальная рекомендация

Генерация аудио PCM-данных в файлы WAV и MP3 с использованием FFMpeg

Справочник статей 1. Получить кодировщик и создать контекст декодера 2. Создайте аудио поток и выведите контекст обертки 3. Записать необработанные данные в файл Формат упаковки аудио WAV может хранит.

Для чего служат интерфейсы comparable и comparator. Смотреть фото Для чего служат интерфейсы comparable и comparator. Смотреть картинку Для чего служат интерфейсы comparable и comparator. Картинка про Для чего служат интерфейсы comparable и comparator. Фото Для чего служат интерфейсы comparable и comparator

3. Wu Weida Machine Учебное примечание Полные сухие товары (глава 3: Линейный регрессионный обзор)

Для чего служат интерфейсы comparable и comparator. Смотреть фото Для чего служат интерфейсы comparable и comparator. Смотреть картинку Для чего служат интерфейсы comparable и comparator. Картинка про Для чего служат интерфейсы comparable и comparator. Фото Для чего служат интерфейсы comparable и comparator

1053 Путь равного веса (30 очков)

1053 Путь равного веса (30 очков) Given a non-empty tree with root R, and with weight W​i​​ assigned to each tree node T​i​​. The weight of a path from R to L&n.

Для чего служат интерфейсы comparable и comparator. Смотреть фото Для чего служат интерфейсы comparable и comparator. Смотреть картинку Для чего служат интерфейсы comparable и comparator. Картинка про Для чего служат интерфейсы comparable и comparator. Фото Для чего служат интерфейсы comparable и comparator

1020 Tree Traversals

Главная мысль: Укажите количество узлов двоичного дерева, а также пост-порядок, результат прохождения среднего порядка и результат прохождения уровня. Идеи решения проблем: Подзадача о бинарном древе.

Для чего служат интерфейсы comparable и comparator. Смотреть фото Для чего служат интерфейсы comparable и comparator. Смотреть картинку Для чего служат интерфейсы comparable и comparator. Картинка про Для чего служат интерфейсы comparable и comparator. Фото Для чего служат интерфейсы comparable и comparator

[OpenStack] Neenron Добавить ICMP и SSH правила (веб-интерфейс)

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

Источник

Пишите компараторы правильно

Как обнаружилось, несоблюдение этих свойств — не такая уж редкая ситуация. Проблема возникает при сравнении вещественных чисел — float или double.

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

Ни рефлексивности, ни антисимметричности не наблюдается. Можно встретить и такую реализацию сравнения:

Здесь все три предыдущих сравнения выдадут ноль, то есть как будто бы свойства соблюдаются. Но, конечно, радоваться рано:

Здесь нарушается транзитивность: первый объект равен второму, второй равен третьему, но первый третьему не равен.

Чем же это грозит простому обывателю? Чтобы понять это, создадим простой список и попробуем его перемешать и посортировать несколько раз:

Вывод в каждом запуске отличается и может выглядеть, например, так:

Или для второй реализации compareTo :

Примерно в половине случаев элемент с NaN прибивается к началу или концу сортируемого списка, а в других случаях начинает блуждать, портя порядок окружающих элементов.

Первый вариант сравнивающей функции психоделичнее. Напишем, например, такой тест:

Мы вставили по пять элементов, содержащих NaN, и по пять элементов, содержащих каждую цифру от 1 до 9. В результате имеем следующее:

Вполне ожидаемо увидеть пять раз NaN: ведь они не равны друг другу. Но из-за неправильных сравнений и некоторые другие элементы вставились по нескольку раз. Можете сами посмотреть, что случится с TreeMap. Заметьте, что один случайно попавший NaN может испортить всю коллекцию, причём это не всегда легко отладить: коллекция может долго существовать в некорректном состоянии и делать вид, что всё нормально.

Что любопытно, этой проблемы вообще не должно существовать. Ещё в JDK 1.4 появились специальные статические методы Float.compare и Double.compare, которые сделают всё за вас, корректно обработав специальные случаи. Надо лишь написать:

Видимо, сказывается обманчивая простота алгоритма сравнения: порой программист считает, что проще написать самому, чем искать в документации стандартный способ сделать это.

Примеры неправильного сравнения double/float в различных открытых проектах: JTS, Batik, Hadoop, Hudson, ICU4J, Lucene. Трудно определить, в каких случаях это может привести к проблемам, но это тот случай, когда я бы исправлял безусловно: правильный и надёжный вариант обычно при этом ещё и короче неправильного.

Чтобы изменить ситуацию, я написал маленький детектор для FindBugs, который находит некорректно реализованные функции сравнения и предлагает использовать Float.compare/Double.compare.

Вообще для всех примитивных типов есть подобные методы. Если вам надо сравнить несколько полей по очереди, можно написать так:

Смотрится лучше, чем куча веток с больше и меньше. А если вы пользуетесь Guava или чем-то подобным, тогда так:

Источник

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

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