可比较的compareTo允许像Comparator nullsFirst或nullsLast这样的空值

nic*_*kl- 1 java

有无数的问题和答案ComparableComparator但似乎没有一个解决这个问题。

假设我有这个方法compare,它接受 a 和 b 的任何Comparable实现并返回比较 -1、0 或 1。

static <U,T extends Comparable<U>> int compare(T a, U b) {
    return a.compareTo(b);
}
Run Code Online (Sandbox Code Playgroud)

与任何Comparable东西一起工作都很好而且花花公子。整个企业的每个项目都采用该方法。

jshell> compare(1, 2);
$1 ==> -1

jshell> compare("id", "hi");
$2 ==> 1
Run Code Online (Sandbox Code Playgroud)

然后数据突然发生变化,我们开始遇到问题。


jshell> compare(null, "hi");
|  Exception java.lang.NullPointerException: Cannot invoke "java.lang.Comparable.compareTo(Object)" because "<parameter1>" is null
|        at compare (#1:2)
|        at (#2:1)

jshell> compare(1, null);
|  Exception java.lang.NullPointerException: Cannot read field "value" because "anotherInteger" is null
|        at Integer.compareTo (Integer.java:1473)
|        at Integer.compareTo (Integer.java:71)
|        at compare (#1:2)
|        at (#3:1)
Run Code Online (Sandbox Code Playgroud)

寻找其他 SO 问题的答案,他们都会重复文档所说的内容:

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

现在这是根本不能接受的!我们有Comparator 类nullsFirst,其中包含这样的方法nullsLast,那么我们如何在不更改方法名称和签名的情况下解决这个问题。我们希望空值小于非空值,并且当两者都为空时,应将它们视为相等。此外,客户非常挑剔,不会接受任何 if equals null 或if (a == null)比较的胡闹。

我们如何更改流行的比较方法以仍然接受任何两个(Comparable包括空值)并产生以下返回。

jshell> compare(1, 2);
$5 ==> -1

jshell> compare("id", "hi");
$6 ==> 1

jshell> compare(null, "hi");
$7 ==> -1

jshell> compare(1, null);
$8 ==> 1

jshell> compare(null, null);
$9 ==> 0
Run Code Online (Sandbox Code Playgroud)

Ste*_*n C 7

你需要修改你的compare方法。改变这个:

static <U,T extends Comparable<U>> int compare(T a, U b) {
    return a.compareTo(b);
}
Run Code Online (Sandbox Code Playgroud)

对此:

static <U,T extends Comparable<U>> int compare(T a, U b) {
    if (a == null) {
        return (b == null) ? 0 : -1;
    } else if (b == null) {
        return +1;
    } else {
        return a.compareTo(b);
    }
}
Run Code Online (Sandbox Code Playgroud)

客户端特别不希望进行任何 if equals null 或 if (a == null) 比较。为什么我们不能简单地使用它,Comparator.nullsFirst因为它已经达到了我们想要的效果?

因为它不起作用。

(更正:实际上,@AndreyB.Panfilov对现已删除的答案发表了评论:

return Comparator.nullsFirst(Comparator.<T>naturalOrder()).compare(a, b);
Run Code Online (Sandbox Code Playgroud)

但这并不影响我接下来要说的内容。)

有时客户的要求太愚蠢了,你不得不推迟。您需要教育客户。严重地。尝试符合他们的最大利益

但是,如果你确实有一个客户毫无理由地坚持认为null文字是撒旦的产物(或其他东西)......你可以null使用Objects.isNulljavadoc)来实现检查。

  • 您可以为该客户提供的最佳服务就是找出他们的推理并向他们解释他们的误解是什么。 (2认同)