当使用Guava时,ImmutableCollection作为函数的参数,最好是要求ImmutableCollection
作为参数类型:
void <T> foo(ImmutableCollection<T> l)
或者该函数应该采用Collection<T>
并在
void <T> foo(Collection<T> l)
{
ImmutableCollection<T> l2 = ImmutableCollection.copyOf(l);
// ...
}
第一个版本似乎更可取,因为调用者确信他传递给函数的地图不会被它修改。但是第一个版本需要带有集合的客户端代码来调用copyOf()
,即:
Collection collection = map.values();
foo(ImmutableCollection.copyOf(collection));
// instead of simply
foo(collection);
PS:这不完全正确,因为ImmutableCollection
没有copyOf()
但ImmutableList
和ImmutableSet
没有。
答案 0 :(得分:3)
我认为这取决于foo
函数应该对集合参数做什么。
如果foo
要阅读集合元素,那么void <T> foo(Collection<T> l)
更可取,因为它会将决定留给调用者。
如果foo
要将集合合并到某个对象的状态中,那么可以优选不可变集合。但是,我们需要问问自己,foo
方法是否应该负责处理此问题,或者调用者的责任。
没有一个权利(或“最佳实践”)答案。但是,使用ImmutableCollection
作为参数的正式类型可能会导致复杂性和/或在某些情况下不必要的复制 。
答案 1 :(得分:2)
查看番石榴文档:"copyOf is smarter than you think."
因此,您可以使用通用Collection
接口,而不会感到遗憾。
在我看来,复制是否必要(而不是功能评论)取决于您持有多长时间的数据。
答案 2 :(得分:0)
使用更通用的Collection
接口;你写一次电话要好得多,要求所有的客户都要在每次电话会议上这样做。如果您真的关心性能,并且性能分析表明它是一个问题,您可以对传入的集合进行类检查,看看是否可以避免复制。
答案 3 :(得分:0)
这取决于foo正在做什么。很可能它只是简单地读取集合值,在这种情况下它不需要复制它,特别是不可变的集合值。
答案 4 :(得分:0)
使用ImmutableCollection
的一个优点是该方法可以保证它不会修改集合。但是那个保证只针对用户,平台不理解它,所以你不妨在评论或自定义注释中表达它。