2015-11-02 72 views
5

Java 8在List接口上引入了一种新的默认方法来对其进行排序。它的签名是:为什么list.sort不使用可选API

void sort(Comparator<? super E> c) 

文档说:

如果指定的比较为null,则在此列表中 所有元素都必须实现Comparable接口和元素的自然 顺序应该被使用。

所以,如果你想通过它的自然顺序排序列表(和您的元素具有可比性),你所要做的list.sort(null);这是一种奇怪的我的意见的。

如果他们使用的是Optional,那么doc会声明您可以选择提供一个比较器,如果没有提供,它会假定这些元素已经可以比较。

A list.sort(null);呼叫将被转换为list.sort(Optional.empty());

由于它是一种暴露于外部世界的方法,我会发现它更准确。

为什么他们没有使用新的可选API呢?

+0

...或者只是强迫你传入一个非空的比较器。我认为这将会更容易。 –

+3

...或匹配'Collections',它提供了一个重载'sort()',它不会使用任何'Comparator'参数来按自然顺序排序? – rgettman

+3

或者只是通过'Comparator.naturalOrder()',它并不那么难,而且比'null'更清晰。 –

回答

12

可选是用作返回类型。这一直是JDK-8开发人员的口头禅。所以他们不会用它作为论据来打破他们自己的规则。

这就是说,我会作出的论点强制性,从而迫使开发者使用

list.sort(Comparator.<Foo>naturalOrder()); 

即使我可以传给空,我发现上面的可读性更强,并没有太大的更详细。所以这就是我在我的代码中使用的。

+0

我不知道第一段,我同意你的最后一点。感谢:) – user2336315

+1

请参阅http://stackoverflow.com/questions/26327957/should-java-8-getters-return-optional-type关于意图的更长的解释,从布赖恩戈茨自己(JDK8的开发人员 - 或任何他的实际称号是) –

+0

谢谢。但是他们也可以提供一个没有参数的默认方法。 – user2336315

1

默认方法是委托给Arrays#sort,其中has existed since at least Java 1.7

下面是默认的方法的相关片段:

@SuppressWarnings({"unchecked", "rawtypes"}) 
default void sort(Comparator<? super E> c) { 
    Object[] a = this.toArray(); 
    Arrays.sort(a, (Comparator) c); 
    ListIterator<E> i = this.listIterator(); 
    for (Object e : a) { 
     i.next(); 
     i.set((E) e); 
    } 
} 

观察,它的转换列表到一个数组,让Arrays#sort从那里处理。此时的默认行为将回退到该方法支持的内容。

有两个原因,我认为这是最好添加一个Optional

  • 如果你不这样做一个Comparator使用,或只是想“默认”的行为,你可以提供一个null它。在这种情况下,nullOptional.isPresent()用于相同的目的,并不会获得任何可用性点。

    这是一个烦恼不得不提供null为它的默认行为的功能;更好的设计可能是要么超载该方法,要么允许传入一个默认的naturalOrder实例。

  • Optional图案更旨在防止无意中处理一null参考,而不是被用于null检查。在添加Optional时,如果简单地检查null就足够了,那么开销会远远超过它的好处,特别是考虑到没有语义差异。

+0

还有'Arrays.sort(Object [] o)',所以他们可以从那里取得值,取决于值是否存在。尽管如此,你说服了我的最后一点,所以+1。 – user2336315

+0

如果他们这样做了,他们会忽略通过哪个*糟糕*设计的参数。在最低限度,用户作为*机会*提供他们自己的“比较器”,但如果他们选择通过'空',则自然顺序获胜。 – Makoto

+0

这并不令人信服。如果参数是'Optional',那么委托给'Arrays.sort'只需要简单地调用'orElse(null)'来将'Optional '转换为可以为null的'Comparator'。但是,一个特定的实现不应该是API设计背后的驱动力(事实并非如此)。顺便说一下,如果一个方法没有“Since”标记,它通常和类本身一样老,这就是'java.util.Arrays'的情况。“* Since:1.2 *” – Holger

相关问题