Comparable和Comparator关于null的合同

Comparable契约指定e.compareTo(null)必须抛出NullPointerException

从API:

请注意, null不是任何类的实例,即使e.equals(null)返回falsee.compareTo(null)应抛出NullPointerException

另一方面, 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的不成文规则?
  • 甚至必须对包含null元素的List进行排序是否是一个好主意,还是设计错误的肯定标志?

  • 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器做什么。


    甚至必须对包含空元素的List进行排序是否是一个好主意,还是设计错误的肯定标志?

    从概念上来说,null意味着“无”,并且在列表中没有任何内容对我来说似乎很奇怪。 另外,Java List合同声明

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

    所以Java中的List实现甚至不需要支持null元素。 总而言之,如果您没有足够的理由将null放入列表中,请不要,如果您确实需要测试它是否按预期工作。


    甚至必须对包含空元素的List进行排序是否是一个好主意,还是设计错误的肯定标志?

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

    这是比较器可接受的用法吗?

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

    链接地址: http://www.djcxy.com/p/76207.html

    上一篇: Comparable and Comparator contract with regards to null

    下一篇: Java: How to check for null pointers efficiently