簡體   English   中英

為什么像 Collections 類中的 sort 方法不在 List 接口中?

[英]Why methods like sort in Collections class are not in List interface?

類 Collections 有一些靜態方法作為實用程序來操作 List 等集合。 例如排序方法 (Collections.sort(list))。 我不明白為什么 Java 規范創建另一個類來承載排序方法(以及所有其他類,如 binarySearch)而不是 List 接口和具體的子類,如 ArrayList 和 LinkedList 實現這些方法。

更新

當我進行了全球研究並閱讀了這篇文章的答案時,我不得不說(鳥瞰):有些人(我提到@dan,@WJS,@cdalxndr)在這篇文章中說,以排序方法為例,因為ArrayList和LinkedList的排序可以用同樣的方式完成,所以我們可以實現一次只寫一次。 所以(我說)我們可以把代碼放在 List 接口中,但是直到 Java 7 我們不能把任何實現放在接口的主體中,一次編寫它的唯一方法是在實用程序類中實現。 但是由於 Java 8 接口具有“默認”方法的特性。 Java 團隊利用這個特性在接口級別實現了 sort 方法,並且該方法可以被 ArrayList 和 LinkedList 使用(如果類沒有覆蓋它,則作為默認值)

排序是一種算法, List是一個容器。

開發人員希望將列表算法(排序、二分搜索等)與容器邏輯(添加、刪除等)分開,因此他們將這些算法放在實用程序類Collections

在 Java 8 之前,接口不能有defaultstatic方法,因此,添加到接口的每個方法都需要由實現該接口的所有類來實現。 即使您在支持類中提供了有用的實現,實現類也至少需要一個委托方法。

因此,除非您想強制所有實現從提供這些方法的某個抽象基類繼承,否則您必須小心添加到接口中的內容。

即使使用default方法,您也必須小心,避免使用太多方法污染實現類的名稱空間。 這也可能是 Java 8 中並非每個操作都被改造成default方法的原因:

雖然向接口添加default方法的侵入性較小,因為它不需要在已經存在的實現類中實現它,但它仍然可能導致與未實現接口方法的實現類的具體方法發生沖突在以前的版本中。

想象一下 Java 之前 8 次的自定義List實現,它提供了一個有用的void sort(Comparator c)實例方法,只是委托給Collections.sort(this, c); . 這在 Java 8 之前有效,沒有提高性能,但允許編寫list.sort(c); . 如今,此方法會無意中覆蓋具有相同名稱和類型的default方法, Collections.sort將委托給該方法,從而產生無限循環(或者更確切地說,遞歸)。

盡管如此, sort方法已添加到List接口中,因為它具有直接的好處。 Collections實用程序類中的static方法不同, default方法可以被覆蓋。 這已針對最常用的列表類型ArrayListVector以及Array.asList(…)返回的實現完成。 由於所有這些實現都由一個數組支持,因此覆蓋方法可以直接使用支持數組委托給Arrays.sort ,而default實現將使用列表內容的臨時副本。

還值得注意的是, Collections中的這些方法最初似乎是基於這些算法適用於所有類型的實現的假設,但並不成立。 在引入 Collection API 之后的兩個版本中,引入了RandomAccess標記接口,以區分兩個根本不同的列表實現類別,因此靜態方法可以基於它分支到兩種替代算法。

每當我們必須基於我們正在操作的類進行分支時,我們可以質疑抽象並說我們最好在類型本身上使用可覆蓋的方法,但如上所述,設計有歷史原因,並且仍然是在向接口添加方法時要小心的理由。

幾分,因為Java的8個選項,只需要你定義(或使用預定義的比較)。

下面的虛擬示例:

    List<Integer> list = new ArrayList();
    list.addAll(List.of(1,5,4,3,6,8,9,2));

    list.sort(Comparator.naturalOrder());

但顯然,作為用戶,它不像在 Collections util 中那樣以相同的方式完成(盡管我確實相信 Collections 實現也使用這樣的比較器或類似的東西)。

因為沒有必要。 以下所有擴展Collection

BeanContext, BeanContextServices, BlockingDeque<E>, BlockingQueue<E>,<br>
Deque<E>, EventSet, List<E>, NavigableSet<E>, Queue<E>, Set<E>,<br>
SortedSet<E>, TransferQueue<E>

所以你提倡的是,每個接口都為Collections每個方法提供完全相同的實現或者可能是一個方便的方法。 恕我直言,那將是一種代碼膨脹。 在前一種情況下,如果發現改進,則需要更改多個實現。

我知道他們在List接口中添加了sort ,也許是因為這是一個常見的要求。 但是我在使用Collections.sort進行排序時從來沒有遇到過問題。 可能還有其他我不知道的原因。

但我傾向於認為CollectionsMath類非常相似。 DoubleInteger沒有重復的數學函數。 Math類似, Collections是一個utility ,它提供了各種可供相關類使用的靜態方法。 當然, Math類不在 Double 或 Integer 等hierarchy ,但其用法非常相似。

集合框架的設計者(主要是在Sun Microsystems工作時的Josh Bloch ),與 Java API 的許多其他部分一樣,都着眼於該語言的壽命。 Java 使用@deprecated標簽將 API 的維持和演變的概念直接合並到文檔支持的語法中。 具體來說,他們預計在發現額外的“容器”操作以添加到CollectionList接口之前,很可能會開發更多的排序和搜索算法。

他們非常清楚接口的變化會給開發團隊帶來升級需求。 升級要求減緩了 Sun Microsystems 希望團隊能夠輕松吸收的修復和改進的采用。 將用於排序和搜索的新方法合並到界面中將極大地阻礙該目標; 給選擇升級到最新版本 Java 語言的團隊帶來了不必要的負擔。 相反,他們明智地選擇將這些實用程序方法分流到靜態實用程序類。

與 Java 8 的List.sort(..) ,我只能猜測Oracle感受到了行業和其他語言將這些常見操作直接納入其集合本身的壓力。 但是,將這些實用程序與集合分開可以最大限度地減少它們對直接實現其接口的人施加的采用要求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM