关于 null 的 Comparable 和 Comparator 合同 [英] Comparable and Comparator contract with regards to null
问题描述
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)
对于所有对象 a
和 b
,其中 !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, ande.compareTo(null)
should throw aNullPointerException
even thoughe.equals(null)
returnsfalse
.
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 comparingnull
and throwingNullPointerException
? - Is it ever a good idea to even have to sort a
List
containingnull
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屋!