为什么Collections.sort不使用比较器,而List.sort必须使用比较器?

问题描述 投票:5回答:3

我不明白为什么List.sort()没有没有比较器的版本的逻辑。

特别是我看到可以用null调用List.sort:list.sort(null),似乎它使用自然顺序进行排序。

我在我的IDE Collections.sort()中注意到调用List.sort(null),所以我想知道为什么Java 8中最近引入的List.sort没有一个没有比较器的简单版本,在许多情况下是不需要的。

此外,在这种情况下,我不确定是否最好调用List.sort(null)以避免进行额外的调用,或者仍然首选调用Collections.sort()并避免使用丑陋的null参数。

java list sorting comparator comparable
3个回答
6
投票

tldr

这是一个设计决策,结合了一些历史原因。可以添加list.sort(),但不能确保仅在运行时的安全性。对于JDK而言,这将是一个相当奇怪且不寻常的设计。


Collections#sort

集合,因为它可以在方法声明中指定类型界限,所以可以强制Comparable元素:

public static <T extends Comparable<? super T>> void sort(List<T> list)

因此该方法可以确保集合包含Comparable个元素。因此不需要Comparator


List#sort

List无法做到这一点。它的泛型类型必须允许所有内容。您可能必须使用List<Dog>,尽管可能不是Comparable

因此,如果存在list.sort(),则此方法将需要确定列表的通用类型T是否为Comparable。但是该信息仅在运行时提供,尽管如此,我们还是希望在编译时提供它来进行漂亮的设计。

因为这将导致不良的设计,所以list.sort()不存在。因此,强制使用Comparator的额外方法可以确保编译时的安全性。


list.sort(null)

list.sort(null)代替list.sort()显然是设计选择,在我看来,这是一个不错的选择。如前所述,List无法确保编译时的安全性。因此,唯一的选择就是追求运行时安全,这不是那么好。

具有仅有时

list.sort()起作用并抛出异常,否则将是一个奇怪的设计选择。但是,像list.sort(null)这样的电话对于任何用户而言都更加清晰。特别是,很显然,这将由运行时决策而不是编译时检查覆盖。

[您可能希望更明确地说明它,并赋予它使用自然顺序的琐碎Comparator

list.sort(Comparator.naturalOrder());

至少读者会更清楚。


历史

[您现在可能想知道为什么List.sort(null)甚至是受支持的功能,为什么它们不要求您始终给它一个明确的Comparator。我无法调查开发人员的想法,但我怀疑历史原因。 JDK中有很多类似的示例,尤其是在排序方面。

这主要是因为Java保持了向后兼容性。 Java 5引入了泛型,因此之前处理容器的所有内容在设计时都没有考虑类型安全。

有两个高度相关的示例:

  • Arrays#sort(Object[])(从Java 1.2开始)不强制Comparable。因此,他们必须在Java 5 Arrays.sort(T[], Comparator)中添加一个额外的重载,就像List示例一样。
  • [方法Collections.sort(T[], Comparator)实际上接受比较器的null。一个糟糕的设计选择,但它是在当时还不存在泛型的情况下做出的。因此他们无法再删除此feature
  • 有趣的是,他们决定让List.sort(Comparator)这一新方法也支持null。但是,在Stream.sort(Comparator)中没有。在JDK中,这是一个奇怪的不一致。

2
投票

当不提供比较器时,将使用natural排序,仅适用于实现Comparable的类型。


1
投票

我不明白为什么list.sort()没有没有比较器的版本的逻辑?

© www.soinside.com 2019 - 2024. All rights reserved.