繁体   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