关于空值的可比合同和比较合同

发布于 2024-09-02 07:28:54 字数 1828 浏览 1 评论 0原文

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

来自API

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

另一方面,比较器 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 和抛出 的不成文规则>空指针异常
  • 甚至必须对包含 null 元素的 List 进行排序是否是一个好主意,或者这是设计错误的明确标志?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

甜是你 2024-09-09 07:28:54

Comparable 不允许 null 的原因很简单:

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

对于所有对象 ab,其中 !a。等于(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 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.

纵山崖 2024-09-09 07:28:54

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

从概念上讲,null 意味着“什么都没有”,在列表中放置任何内容对我来说似乎很奇怪。此外,Java List 合约指出

某些列表实现对其可能包含的元素有限制。例如,某些实现禁止 null 元素

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

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?

Conceptually, null means "nothing", and placing nothing in a list seems weird to me. Also, the Java List contract states that

Some list implementations have restrictions on the elements that they may contain. For example, some implementations prohibit null elements

so a List implementation in Java is not even required to support null elements at all. To sum up, if you do not have a good reason to put null into a list, don't, and if you do, test that it actually works as expected.

小巷里的女流氓 2024-09-09 07:28:54

甚至不得不这样做是个好主意吗?
对包含空元素的列表进行排序,
或者这是设计的明确标志
错误?

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

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

BeanComparator 允许您对企业中的属性进行排序对象,即使属性包含 null,所以我不得不说这是比较器的可接受的使用。

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?

Well, it probably doesn't make sense for the list to contain a null Object, but maybe your List contains a "business object" and you can sort on different properties of the business object, some of which may contain nulls.

Is this an acceptable use of a
Comparator

The BeanComparator allows you to sort on a propery in a business object even if the property contains null, so I would have to say it is an acceptable use of a Comparator.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文