Комментарии 16
Согласно документации использование Comparable возможно, если для сравнения используется естественный порядок (class's natural ordering).
Документация (SE 8):
public interface ComparableThis interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method.
А можете пальцем показать, где вы тут нашли «возможно, если»? Вот тут не так написано. Тот порядок, который задается Comparable, называется естественным. Если вам такой порядок нужен — используйте a.compareTo(B). Если нет — пишете компаратор.
Однако это не дает формальных правил чтобы разработчик смог понять, может он он в своем классе имплементировать Comparable или нет.
для меня использование .compareTo
омрачается необходимостью проверки на NULL каждый раз.
с java знаком шапочно, может быть я что-то не так понимаю.
Также в этой статье я не затрагивал проблему total order, когда compareTo возвращает 0. Так как она одинаковая для обоих интерфейсов сравнения.
Обычно в пользовательском коде не требуется явно вызвать .compareTo, это делают за нас сортировщики у коллекций, стримов и прочего.
хорошо, а как тогда сравнивать «в пользовательском коде»?
private void someMethod(BigDecimal b) {
if ( b.compareTo(BigDecimal.ZERO) <= 0 ) {
// value must be positive, abort
}
// do something
}
приходится или вставлять проверку на NULL (что загрязняет код), или «переворачивать» условие (что опять же плохо читается), или писать отдельную функцию-компаратор.
P. S. впрочем, понятно, что тут дело не в compareTo
, а в обработке NULL в java. может быть оно сделано правильно, но мне «не зашло» )
first
, в т.ч. first.compareTo(second)
, и эта ссылка может содержать значение null
, то нужно обрабатывать случаи first = null
и first != null
как это делаете Вы.Более того, если
second
может содержать null
, тогда или перед вызовом метода compareTo()
, или внутри него, нужно предусмотреть обработку случаев с second = null
и second != null
.Можно также написать компаратор, который обрабатывает оба значения как
nullable
. В целом это не проблема сравнения, это проблема обработки nullable
ссылок.Было бы интересно посмотреть контекст, в котором Вы используете этот метод. Если его приходится дергать руками, то есть ли смысл вообще делать свой класс реализацией Comparable?
речь в данном случае не про свой класс, а про BigDecimal (ну и не только, но сравнений BigDecimal в коде много и выглядит на мой взгляд это «так себе»).
да, мой комментарий не имеет отношения к статье )
В целом это не проблема сравнения, это проблема обработки nullable ссылок.
это понятно. непонятно как писать красиво.
compareTo
, и понял что оно действительно активно используется при работе с BigDecimal
.В целом подход проверки на
null
остается тот же. Если везде логика обработки разная, то придется в каждом месте проверять условие. Если логику можно сделать одинаковой в разных местах, то следует вынести ее в отдельный метод. Реализовать этот метод в виде утилитного в текущем классе с бизнес логикой, или же в виде компаратора — дело вкуса.или «переворачивать» условие (что опять же плохо читается), или писать отдельную функцию-компаратор
Если посмотреть в код компаратора BigDecimal, можно увидеть, что переворот условия не сработает.
Иногда программистам очень неудобно работать с ссылками на null
. Например, вы сравниваете две строки. Если обе переменные не null
, тогда можно просто вызвать s1.equals(s2)
, и все будет работать. А вот если s1
может быть null
, придется писать код, который учитывает эту ситуацию, чтобы не возникло NullPointerException
.
Поэтому программисты придумали служебный класс Optional<T>.
Один объект Optional
всегда можно сравнить с другим объектом Optional
через метод equals
, даже если они хранят в себе ссылки на null
.
Грубо говоря, класс Optional позволяет «более красиво» записывать проверки на null
и действия в случае, если внутри объект Optional
хранится null
.
А что скажите про thenComparing у компараторов?
Я это к чему? При казалось бы похожей сфере применимости, у Comparator и Comparable, все-таки есть случаи, когда их возможности расходятся. Именно поэтому существуют различные языковые конструкции.
И то и другое являются интерфейсами разных пакетов. И одно и второе может имплементить в один и тот же класс.
Данная статья хорошо подходит джунам, но для джунов надо сначала разжевать, что такое Comparator, потом Comparable, привести пример с созданием классов и имплементации. И выкинуть
неявно: Arrays.sort(accountsList)
явно: Arrays.sort(accountsList, accountByValueComparator)
и статья станет не плохой. Доработайте, пожалуйста)
Технически можно сделать чтобы класс имплементировал для самого себя интерфейс компаратора (или валидатора, сериализатора). На практике это явное слияние зон ответственности, и вряд ли будет использоваться. Вопрос в том чтобы убрать слово «отдельный»?
Как без использования примеров явно/неявно подвести к проблеме поиска использований определенного метода compareTo?
Выбор между Comparator и Comparable