Контракт сравнимый и компаратор по нулю - PullRequest
35 голосов
/ 18 мая 2010

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

С API :

Обратите внимание, что null не является экземпляром какого-либо класса, и e.compareTo(null) должен выдать NullPointerException, даже если e.equals(null) возвращает false.

С другой стороны, Comparator API ничего не упоминает о том, что должно происходить при сравнении null. Рассмотрим следующую попытку универсального метода, который принимает Comparable и возвращает Comparator для него, который устанавливает null как минимальный элемент.

static <T extends Comparable<? super T>> Comparator<T> nullComparableComparator() {
   return new Comparator<T>() {
      @Override public int compare(T el1, T el2) {
         return
            el1 == null ? -1 :
            el2 == null ? +1 :
            el1.compareTo(el2);
      }
   };
}

Это позволяет нам делать следующее:

List<Integer> numbers = new ArrayList<Integer>(
   Arrays.asList(3, 2, 1, null, null, 0)
);
Comparator<Integer> numbersComp = nullComparableComparator();
Collections.sort(numbers, numbersComp);
System.out.println(numbers);
// "[null, null, 0, 1, 2, 3]"

List<String> names = new ArrayList<String>(
   Arrays.asList("Bob", null, "Alice", "Carol")
);
Comparator<String> namesComp = nullComparableComparator();
Collections.sort(names, namesComp);
System.out.println(names);
// "[null, Alice, Bob, Carol]"

Итак, вопросы:

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

Ответы [ 3 ]

25 голосов
/ 18 мая 2010

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)

необходимо оценить до true, чтобы выполнить соответствующие контракты.

Так что null не разрешено, потому что вы не можете сделать:

null.compareTo(a)

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

8 голосов
/ 18 мая 2010

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

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

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

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

4 голосов
/ 18 мая 2010

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

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

Является ли это приемлемым использованием Компаратор

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

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