集合层次结构应该是Collection(只读) - > ModifiableCollection

时间:2014-12-22 12:00:42

标签: java

当前的java框架提供了一个Collection类,然后是一种从集合中获取“不可修改”集合的方法。没有类别对应于公开暴露的不可修改的集合。如果我要重新设计一个Collection类层次结构,我会有一个Collection接口(只读),子类为ModifiableCollection(可以修改)。当前的方法是不充分的,因为它只提供运行时错误检查而不是编译时间检查。在层次结构的基础上使用显式只读集合类将避免运行时错误。

请注意,我在这里指的是只读集合,而不是不可变的,尽管概念类似。见https://stackoverflow.com/a/27611460/4350148

这个问题的动机部分是由于我在编写代码时遇到的问题。我发现有时我在已经无法修改的集合上调用Collections.unmodifiableCollection(Collection col)。该方法只是再次包装集合。对于只读版本,每个方法都会更清楚,返回什么样的集合以及方法是否可以更改其中一个集合类型参数的内容。

这种方法会更有意义吗?或者我在这里遗漏了什么?

2 个答案:

答案 0 :(得分:3)

这被考虑并被拒绝,因为它会导致集合层次结构中的接口和类太多:

  

为什么不直接在核心集合中支持不变性   接口,以便您可以取消可选操作(和   UnsupportedOperationException异常)吗

     

这是整个API中最具争议的设计决策。   显然,静态(编译时)类型检查是非常需要的,并且   是Java的常态。如果我们相信的话,我们会支持它   可行。不幸的是,实现这一目标的尝试导致了   接口层次结构的大小爆炸,并没有成功   消除了对运行时异常的需求(尽管它们减少了它)   基本上)。

     Doug Lea编写了一个流行的Java集合包   不再反映其界面层次结构中的可变性区别   相信这是一种可行的方法,基于用户的经验   收藏包。用他的话说(来自个人通信)“很多   因为我很难说,强大的静态打字不起作用   Java中的集合接口。“

     

为了说明血腥细节中的问题,假设您要添加   层次结构的可修改性概念。你需要四个新的   interfaces:ModifiableCollection,ModifiableSet,ModifiableList和   ModifiableMap。以前简单的层次结构现在是一个混乱的   异质观。此外,您还需要一个新的Iterator接口   不可修改的集合,不包含删除操作。   你现在可以取消UnsupportedOperationException吗?不幸   不

     

考虑数组。它们实现了大部分List操作,但没有   删除并添加。它们是“固定大小”的列表。如果你想捕捉   在层次结构中的这个概念,您必须添加两个新接口:   VariableSizeList和VariableSizeMap。你不必添加   VariableSizeCollection和VariableSizeSet,因为它们是   与ModifiableCollection和ModifiableSet相同,但您可以   为了保持一致性,无论如何都要选择添加它们。此外,你需要一个新的   各种不支持添加和删除的ListIterator   操作,与不可修改的List一起使用。现在我们达到十或   12个接口,加上两个新的Iterator接口,而不是我们的   原四。我们完了吗?否。

     

考虑日志(例如错误日志,审核日志和日志)   可恢复的数据对象)。它们是天然附加序列,   支持除remove和set之外的所有List操作   (更换)。它们需要一个新的核心接口和一个新的迭代器。

     

那么不可变的集合呢,而不是不可修改的集合呢?   (即,客户不能更改的集合,永远不会   因任何其他原因而改变)。许多人认为这是最多的   所有的重要区别,因为它允许多个线程   无需同步即可同时访问集合。   将此支持添加到类型层次结构还需要四个   接口

     

现在我们有大约20个接口和5个迭代器,而且它是   几乎可以肯定,在实践中仍然存在收藏品   不适合任何接口。例如,   Map返回的集合视图是自然删除集合。   此外,有些集合会拒绝某些元素   它们的价值基础,所以我们仍然没有废除运行时   异常。

     

当一切都说完了,我们觉得这是一个合理的工程   通过提供一个非常小的集来妥协以回避整个问题   可能引发运行时异常的核心接口。

Source

答案 1 :(得分:0)

Collection继承自Iterable,这是一个只读版本。 Iterable可以简单地用于遍历Collection,并且是任何Collection的只读版本。

对于Iterable上的其他操作,您可以将其转换为Stream,该StreamSupport也是只读的{{1}}。 {{1}}。

请参阅this SO for more input