Сопоставимый и Компаратор сокращаются относительно пустого указателя

Comparable контракт указывает это e.compareTo(null) должен бросить NullPointerException.

От API:

Отметьте это null не экземпляр никакого класса, и e.compareTo(null) должен бросить a NullPointerException даже при том, что 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]"

Таким образом, вопросы:

  • Это приемлемое использование a Comparator, или это нарушает незаписанное правило относительно сравнения null и бросок NullPointerException?
  • Это - когда-нибудь хорошая идея даже должным быть отсортировать a List содержа null элементы, или это - верный признак ошибки дизайна?

35
задан polygenelubricants 18 May 2010 в 15:36
поделиться

3 ответа

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 является проблемой, зависящей от реализации. Поддерживать его или нет, в зависимости от того, что вы хотите, чтобы ваш Компаратор делал.

25
ответ дан 27 November 2019 в 15:41
поделиться

Было ли когда-нибудь хорошей идеей даже сортировать список, содержащий нулевые элементы, или это верный признак ошибки дизайна?

По сути, null означает «ничего», и размещение ничего в списке кажется странным мне. Кроме того, в контракте Java List указано, что

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

, поэтому реализация List в Java даже не требуется для поддержки нулевых элементов. Подводя итог, если у вас нет веской причины помещать null в список, не делайте этого, а если да, проверьте, действительно ли он работает так, как ожидалось.

8
ответ дан 27 November 2019 в 15:41
поделиться

Это когда-нибудь хорошая идея даже иметь отсортировать список, содержащий нулевые элементы, или это верный признак дизайна ошибка?

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

Допустимо ли это использование Comparator

BeanComparator позволяет вам сортировать свойство в бизнес-объекте, даже если свойство содержит null, поэтому я должен сказать, что это приемлемое использование Comparator.

4
ответ дан 27 November 2019 в 15:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: