簡體   English   中英

為什么不使用Collections類的不可修改方法來創建具有新元素的集合?

[英]Why don't the unmodifiable methods from Collections class, create collections with new elements?

假設有以下代碼:

List<String> modifiableList = new ArrayList<String>(Arrays.asList("1","2","3"));
List<String> unmodifiableList = Collections.unmodifiableList(modifiableList);
System.out.println(unmodifiableList);
modifiableList.remove("1");
modifiableList.remove("3");
System.out.println(unmodifiableList);

它打印

[1, 2, 3]
[2]

如果將第二行更改為

List<String> unmodifiableList = Collections.unmodifiableList(
                                       new ArrayList<String>(modifiableList));

它按預期工作。 問題是,為什么Collections的UnmodifiableList內部類(以及所有其他不可修改的類)為什么不創建原始列表的新副本,例如ArrayList的構造函數是否真的使其無法修改?

編輯:我了解代碼的作用; 我的問題是為什么以這種方式實施? 為什么在創建基礎數組的新副本時,UnmodifiableList(Collections的內部類)中的構造函數的行為類似於ArrayList的構造函數? 為什么可修改的集合(ArrayList)復制整個內容,而不可修改的集合則不復制?

原因是效率簡單。 復制集合中的所有元素可能會非常耗時,特別是如果要包裝的集合具有某種不可思議的效果(例如JPA延遲加載),並且需要額外的內存。 按原樣包裝基礎集合是一項微不足道的操作,不會增加任何額外的開銷。 如果開發人員確實確實想要單獨的副本(無論是否不可修改),則顯式創建它非常容易。 (我傾向於為此使用番石榴Immutable* 。)

這些方法的目的是在現有集合上創建不可修改的視圖 這就是記錄的行為,而且在許多情況下,這正是你想要的東西-它比復制所有數據,比如更有效的...或者你想手工調用者的集合,這反映要進行任何更改,但沒有允許他們做出改變。

如果您想要數據的不可變副本 (或至少是引用...),則只需創建一個副本,然后在其頂部創建不可變視圖即可,就像您一樣。

因此,基本上,您可以根據執行視圖操作的Collections.unmodifiable*本身輕松地創建視圖或復制視圖。 因此,我們有兩個正交運算:

  • 創建一個副本(例如通過構造函數)
  • 創建一個視圖(通過Collections.unmodifiable*

這些操作可以很容易地組成。 如果Collections.unmodifiable*實際執行“復制唯一”,那么我們就需要為只是做一個視圖等操作。 如果您接受這兩個選項在不同情況下都是有用的,則使它們可組合可提供很大的靈活性。

請注意,unmodifiableList返回所提供列表的“ unmodifiable view ”。 因此,列表本身停留在該列表上(它仍然可以修改),只有其“不可修改的視圖”是不可修改的。 您可以將其視為SQL表和視圖---您可以在表上運行DML腳本,並且它將反映在相關視圖上。 至於ArrayList ---它由...支持,因此它是實現的功能,它從提供的源列表中復制元素(實際上不必由數組支持)。 它能回答您的問題嗎?

暫無
暫無

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

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