Comparable
контракт указывает это e.compareTo(null)
должен бросить NullPointerException
.
От API:
Отметьте это
null
не экземпляр никакого класса, иe.compareTo(null)
должен бросить aNullPointerException
даже при том, чтоe.equals(null)
возвратыfalse
.
С другой стороны, Comparator
API ничего не упоминает о какой потребности произойти при сравнении null
. Рассмотрите следующую попытку общего метода, который берет a Comparable
, и возвратите a Comparator
для него, который помещает null
как минимальный элемент.
static > Comparator nullComparableComparator() {
return new Comparator() {
@Override public int compare(T el1, T el2) {
return
el1 == null ? -1 :
el2 == null ? +1 :
el1.compareTo(el2);
}
};
}
Это позволяет нам делать следующее:
List numbers = new ArrayList(
Arrays.asList(3, 2, 1, null, null, 0)
);
Comparator numbersComp = nullComparableComparator();
Collections.sort(numbers, numbersComp);
System.out.println(numbers);
// "[null, null, 0, 1, 2, 3]"
List names = new ArrayList(
Arrays.asList("Bob", null, "Alice", "Carol")
);
Comparator namesComp = nullComparableComparator();
Collections.sort(names, namesComp);
System.out.println(names);
// "[null, Alice, Bob, Carol]"
Таким образом, вопросы:
Comparator
, или это нарушает незаписанное правило относительно сравнения null
и бросок NullPointerException
?List
содержа null
элементы, или это - верный признак ошибки дизайна? Comparable
не позволяет null
просто потому, что:
a.compareTo(b) == -b.compareTo(a)
для всех объектов a
и b
где ! a.equals (b)
. Более конкретно:
a.equals(b) ? b.equals(a) && a.compareTo(b) == 0 &&
b.compareTo(a) == 0 && a.hashCode() == b.hashCode()
: !b.equals(a) && a.compareTo(b) != 0 &&
a.compareTo(b) == -b.compareTo(a)
должен быть оценен как истинно
для выполнения соответствующих контрактов.
Таким образом, null
не допускается, потому что вы не можете этого сделать:
null.compareTo(a)
Компаратор
более гибкий, поэтому обработка null
является проблемой, зависящей от реализации. Поддерживать его или нет, в зависимости от того, что вы хотите, чтобы ваш Компаратор
делал.
Было ли когда-нибудь хорошей идеей даже сортировать список, содержащий нулевые элементы, или это верный признак ошибки дизайна?
По сути, null означает «ничего», и размещение ничего в списке кажется странным мне. Кроме того, в контракте Java List указано, что
Некоторые реализации списков имеют ограничения на элементы, которые они могут содержать. Например, некоторые реализации запрещают нулевые элементы
, поэтому реализация List в Java даже не требуется для поддержки нулевых элементов. Подводя итог, если у вас нет веской причины помещать null в список, не делайте этого, а если да, проверьте, действительно ли он работает так, как ожидалось.
Это когда-нибудь хорошая идея даже иметь отсортировать список, содержащий нулевые элементы, или это верный признак дизайна ошибка?
Что ж, вероятно, не имеет смысла содержать в списке нулевой объект, но, возможно, ваш список содержит «бизнес-объект», и вы можете сортировать по различным свойствам бизнес-объекта, некоторые из которых могут содержать нули.
Допустимо ли это использование Comparator
BeanComparator позволяет вам сортировать свойство в бизнес-объекте, даже если свойство содержит null, поэтому я должен сказать, что это приемлемое использование Comparator.