36

Comparable合同规定e.compareTo(null)必须抛出NullPointerException

API

请注意,null它不是任何类的实例,即使返回,也e.compareTo(null)应该抛出一个。NullPointerExceptione.equals(null)false

另一方面,ComparatorAPI没有提及比较时需要发生什么null。考虑以下尝试使用 a 的泛型方法,并为其Comparable返回 a作为最小元素。Comparatornull

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]"

所以问题是:

  • 这是 a 的可接受用法Comparator,还是违反了关于比较null和抛出的不成文规则NullPointerException的不成文规则?
  • List甚至必须对包含的元素进行排序是一个好主意null,还是这是设计错误的明确标志?
4

3 回答 3

25

Comparable不允许null仅仅是因为:

a.compareTo(b) == -b.compareTo(a)

对于所有对象ab位置!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做什么。

于 2010-05-18T15:28:44.107 回答
8

甚至必须对包含空元素的列表进行排序是一个好主意,还是这是设计错误的明确迹象?

从概念上讲,null 表示“无”,在列表中放置任何内容对我来说似乎很奇怪。此外,Java List 合同规定

一些列表实现对它们可能包含的元素有限制。例如,一些实现禁止空元素

因此,Java 中的 List 实现甚至根本不需要支持 null 元素。总而言之,如果您没有充分的理由将 null 放入列表中,请不要这样做,如果这样做,请测试它是否确实按预期工作。

于 2010-05-18T15:31:12.790 回答
4

甚至必须对包含空元素的列表进行排序是一个好主意,还是这是设计错误的明确迹象?

好吧,列表包含空对象可能没有意义,但也许您的列表包含一个“业务对象”,您可以对业务对象的不同属性进行排序,其中一些可能包含空值。

这是比较器的可接受使用吗

BeanComparator允许您对业务对象中的属性进行排序,即使该属性包含 null,所以我不得不说它是 Comparator 的可接受使用。

于 2010-05-18T16:35:19.657 回答