2014-12-22 61 views
0

當前的Java框架提供了一個Collection類,然後從集合中獲取「不可修改」集合。沒有對應於公開公開的不可修改集合的類。如果我要重新設計一個Collection類層次結構,我將有一個Collection接口(它是隻讀的),其子類爲ModifiableCollection(可以對其進行修改)。目前的方法是不夠的,因爲它只提供運行時錯誤檢查而不是編譯時檢查。通過在層次結構底部的顯式只讀集合類,可以避免運行時錯誤。集合層次結構應爲Collection(只讀) - > ModifiableCollection

請注意,我指的是隻讀集合,而不是不可變的,雖然概念是相似的。見https://stackoverflow.com/a/27611460/4350148

這個問題的部分原因是由於我在編寫代碼時遇到的問題。我發現有時我對已經不可修改的集合調用Collections.unmodifiableCollection(Collection col)。該方法只是簡單地包裝收集。對於只讀版本,每種方法都會更清楚,返回的是哪種集合,以及方法是否可以更改其中一個集合類型參數的內容。

這種方法會更有意義嗎?或者我在這裏錯過了什麼?

+0

如果你傳遞一個可變的集合,它假定它是不可變的方法,但你在代碼的其他地方改變這個集合,有可能在另一個線程。然後它不是真正的不可變的,只是被調用者不能改變它,除非帶有不可變引用的方法將它轉換爲可變的引用。 –

+1

@PeterLawrey我只在這裏讀過,我並不是指不可變的。他們是不一樣的 –

回答

0

Collection繼承自Iterable這是一個只讀版本。 Iterable可以簡單地用於遍歷Collection,並且是任何Collection的只讀版本。

對於Iterable上的其他操作,您可以將其轉換爲Stream,該文件也是隻讀的,例如, StreamSupport

請參閱this SO for more input

3

這被認爲和拒絕,因爲它會導致過多的接口和類的集合層次:

你爲什麼不直接支持不變性的核心種質 接口,使您可以取消可選操作(和 UnsupportedOperationException)?

這是整個API中最具爭議性的設計決策。 顯然,靜態(編譯時)類型檢查是非常需要的,並且 是Java中的常態。如果我們認爲 可行,我們會支持它。不幸的是,試圖實現這個目標會導致接口層次的大小增加 ,並且不會成功地消除對運行時異常的需求(儘管它們實質上減少了 )。

Doug Lea的,誰寫流行的Java集合包,確實 反映易變性的區別在它的接口層次,不再 認爲這是一個可行的方法的基礎上,與他 收藏包的用戶體驗。用他的話說(來自個人通信)「很多 ,因爲它很難說,強靜態類型不適用於Java中的集合接口。「

爲了說明在血淋淋的細節問題,假設你想在 概念可修改的添加到層級需要四個新 接口:ModifiableCollection,ModifiableSet,ModifiableList和 ModifiableMap什麼是以前簡單的層次結構現在是一個混亂的 異質觀。另外,你需要使用一個新的Iterator接口與 不可修改的集合,即不包含刪除操作。 現在你能破除UnsupportedOperationException異常?不幸的是 沒有。

考慮陣列。他們實現了大部分List操作口糧,但不是 刪除和添加。他們是「固定大小」列表。如果要在層次結構中捕獲 這個概念,則必須添加兩個新接口: VariableSizeList和VariableSizeMap。您不必添加 VariableSizeCollection和VariableSizeSet,因爲它們將與與ModifiableCollection和ModifiableSet相同,但您可能爲了一致性而選擇添加它們。此外,您需要一個新的不支持添加和刪除 操作的ListIterator的各種Listyterator,以配合不可修改的List。現在我們可以多達十個或 十二個接口,再加上兩個新的Iterator接口,而不是我們的 原來的四個。我們完了嗎?編號

考慮日誌(如錯誤日誌,審計日誌和 可恢復數據對象的日誌)。它們是自然附加序列, 支持除刪除和設置 (替換)之外的所有列表操作。他們需要一個新的核心接口和一個新的迭代器。

那麼不可變的集合,而不是不可修改的集合呢? (即,不能由客戶更改的集合AND將不會由於任何其他原因而更改 )。許多人認爲這是最重要的區別,因爲它允許多個線程同時訪問集合而不需要同步。 將此支持添加到類型層次結構中需要四個以上的 接口。

現在我們可以使用二十個左右的接口和五個迭代器,而且它的 幾乎可以確定在實踐中出現的集合 不適合任何接口。例如,Map返回的 集合視圖是自然的只刪除集合。 此外,還有一些集合會拒絕某些元素的基於它們的值的 ,所以我們仍然沒有廢除運行時的例外情況 。

當所有說過和做過,我們認爲,這是一個合理的工程 妥協通過提供能夠引發運行時異常核心接口極少量的 迴避整個問題。

Source

+0

感謝張貼這個。我不同意「先前簡單的層次結構現在是一個混亂的層次結構。」確實,收集類的數量會增加一倍,但從概念上講,它不會增加很多複雜性。有趣的是,添加這些被認爲是「凌亂的層次」。我也不明白關於數組的聲明和對可變大小列表類的需求。你的想法 –

+0

@danb考慮'Arrays.asList()'。這個方法返回一個'List'實現,如果你試圖調用'add'或'remove',則拋出一個異常。如果你想消除所有'UnsupportedOperationException'異常,你需要一些'FixedLengthList'接口將數組轉換爲List。這只是爲了消除UnsupportedOperationException異常而必須添加的所有接口的一個示例。有太多的接口會使得學習如何使用Collections層次結構變得更加困難。 – Eran

+0

我認爲你只需要一個List(只讀)和一個ModifiableList(如前所述)和兩個方法Array.asList() - >返回List和Arrays.asModifiableList() - >返回ModifiableList。所以這只是另一種鏡像方法。 –