2015-11-02 139 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

相關問題