我想在获得类型安全的同时返回一个不可修改的集合。尽管我希望这很容易做到,但我似乎找不到这个。
假设我有一个类 Foo,其中包含一个大类 Bar 的集合,足够大以至于需要一段时间才能克隆。我希望作为紧密循环的一部分迭代 Foo 中 Bar 的每个元素,因此我的 Foo 对象上有一个 getBars() 方法
我不想将 foo 中的集合直接传递给调用 getBar() 的人,因为这将允许任何人修改该集合,这是不安全的。所以我的选择是
1) 将我的 Foo 集合复制到新集合中 2)返回Collections.unmodifyingCollections 第一个选项需要复制所有内容,这在紧密循环中成本很高,而且我预计在返回后不需要修改集合。第二个选项可以满足我的要求,但最终用户并不知道所发生的事情。如果后来有人因为某种原因决定要修改 getBar 返回的集合,他们将在调用 add 或 remove 时得到一个异常,这在代码中没有明确记录(是的,API 会记录它,但不会记录它)相同)。
我想要的是有一个 UnmodifyingCollection 类,它包装我的实际集合,并且只使 getter 可见,但 setter 不可见。它会很快,因为它只是包装而不是复制底层集合,并且它会是自记录的,您无法修改集合,以后不会有人遇到意外的运行时异常。
我想知道的是这个存在吗!?它看起来很基本,Guava 应该有它,但我在任何地方都找不到它。如果它不存在,是否有某种原因导致这比我想象的更难或不太有用? 诗。据我所知,Guava immutableCollections 都会复制底层集合,所以它们相当于上面的选项 1
最佳答案
java.util.Collections API 设计不可能实现。
所有标准集合 API 都设计为可变的,因此只要您想使用集合接口(interface),就无能为力。
您可以切换到 return (您自己的实现)枚举(有点过时的接口(interface)),或简单的迭代器(getBarIterator() 而不是 getBarList())。这避免了任何添加/删除方法的所有(或大部分)影响。通过这种方式,您公开的信息/功能明显减少,这可能是一个问题或期望,具体取决于用例。对于 Iterator,您仍然可以在迭代器上使用 remove() 方法,客户端可以尝试使用该方法来获取 UnsupportedOperationException()/IllegalStateException()。
一直困扰我的是集合API的读取和修改方法都是在同一个接口(interface)中。无论出于何种原因,API 设计者选择按原样设计它,并且由于它现在已广泛建立,因此无法更改(在不破坏兼容性的情况下,这与“不可更改”一样好)。
如果这些都不适合,并且您重视干净的 API 安全性高于使用标准 API,请推出您自己的不可变 API。
编辑: 我个人对这个困境的解决方案是创建一组可更改包装器。他们实现了普通的集合 API(List、Set、Map),最初他们只是将所有内容委托(delegate)给他们的源集合。在第一次写入尝试时,它们会复制其源代码,并在之后作为正常的独立集合运行。请注意,实现,尤其是 iterator().remove() 的实现可能很棘手。
关于java - 在哪里可以找到类型安全的不可修改集合实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23917921/