关于 null 的 Comparable 和 Comparator 合同 [英] Comparable and Comparator contract with regards to null

查看:34
本文介绍了关于 null 的 Comparable 和 Comparator 合同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

来自API:><块引用>

注意 null 不是任何类的实例,并且 e.compareTo(null) 应该抛出一个 NullPointerException 即使 e.equals(null) 返回 false.

另一方面,比较器 API 没有提到在比较 null 时需要发生什么.考虑以下通用方法的尝试,该方法采用 Comparable,并为其返回一个 Comparator,将 null 作为最小元素.>

static >比较器 TnullComparableComparator() {返回新的比较器(){@Override public int compare(T el1, T el2) {返回el1 == 空?-1 :el2 == 空?+1 :el1.compareTo(el2);}};}

这允许我们执行以下操作:

List数字 = 新的 ArrayList(Arrays.asList(3, 2, 1, null, null, 0));比较器<整数>numbersComp = nullComparableComparator();Collections.sort(numbers, numbersComp);System.out.println(数字);//"[null, null, 0, 1, 2, 3]"列表<字符串>名称 = 新的 ArrayList(Arrays.asList("Bob", null, "Alice", "Carol"));比较器<字符串>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 做什么.

Comparable contract specifies that e.compareTo(null) must throw NullPointerException.

From the API:

Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false.

On the other hand, Comparator API mentions nothing about what needs to happen when comparing null. Consider the following attempt of a generic method that takes a Comparable, and return a Comparator for it that puts null as the minimum element.

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);
      }
   };
}

This allows us to do the following:

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

So the questions are:

  • Is this an acceptable use of a Comparator, or is it violating an unwritten rule regarding comparing null and throwing NullPointerException?
  • Is it ever a good idea to even have to sort a List containing null elements, or is that a sure sign of a design error?

解决方案

Comparable doesn't allow null simply because:

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

for all objects a and b where !a.equals(b). More specifically:

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)

must evaluate to true to satisfy the relevant contracts.

So null isn't allowed because you can't do:

null.compareTo(a)

Comparator is more flexible so handling of null is an implementation-specific issue. Support it or not depending on what you want your Comparator to do.

这篇关于关于 null 的 Comparable 和 Comparator 合同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆