Русский
Русский
English
Статистика
Реклама

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

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

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

UserAccount {  currency  value  updatedTimestamp}

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

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

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

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

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

  • Создается отдельный класс, реализующий интерфейс Comparator<UserAccount>, и дальше объект этого класса может сравнить между собой два объекта исходного класса: userAccountComparator.compare(acc1, acc2)

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

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

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

  • неявно: Arrays.sort(accountsList)

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

Чтобы разработчику узнать правила сортировки в первом случае ему нужно будет посмотреть, как реализован метод compareTo у класса UserAccount, а во втором - у accountByValueComparator. Здесь разницы нет. Но посмотрим на обратную задачу. Пусть разработчик видит перед собой код

UserAccount implements Comparable<UserAccount> {  @Override  public int compareTo(UserAccount other) { .. }}

Как определить, где используется объявленный метод compareTo ? Если искать по использованию метода, то потребуется включить в поиск и метод суперкласса Comparable#compareTo, так как именно он будет найден в Arrays.sort(). Но метод суперкласса используется также в огромном количестве других мест внутри кода jdk, и найти таким образом его будет сложно. Я не нашел способов искать такие использования методов кроме как ручным перебором: ищем все включения класса UserAccount и ниже по стеку обращаем внимание на все Arrays.sort(), stream.sorted() и тд.

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

Резюмируя - в большинстве случаев аргументы за использование Comparator перевешивают аргументы за использование Comparable.

Источник: habr.com
К списку статей
Опубликовано: 18.10.2020 22:23:47
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Java

Java core

Comparator

Comparable

Explicit is better th... oh shut up

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru