4

当使用 Guava 的ImmutableCollection作为函数的参数时,最好要求ImmutableCollection作为参数类型:

void <T> foo(ImmutableCollection<T> l)

或者该函数应该采用 aCollection<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()but ImmutableListand ImmutableSetdo。

4

5 回答 5

3

我认为这取决于foo函数应该对集合参数做什么。

  • 如果foo要读取集合元素,则更void <T> foo(Collection<T> l)可取,因为它将决定留给调用者。

  • 如果foo要将集合合并到某个对象的状态中,那么不可变集合可能更可取。但是,我们接下来需要问自己,处理这个问题应该是foo方法的责任,还是调用者的责任。

对此没有一个正确(或“最佳实践”)的答案。但是,在某些情况下ImmutableCollection,用作参数的正式类型可能会导致复杂性和/或不必要的复制。

于 2013-08-12T13:26:13.227 回答
2

看看番石榴文档:“copyOf 比你想象的更聪明。”

因此,您可以使用通用Collection接口而不会对性能感到遗憾。

在我看来,副本是否必要(而不是函数注释)取决于您保留数据的时间。

于 2013-08-12T14:44:44.147 回答
0

使用更通用的Collection接口;编写一次调用比要求所有客户端在每次调用时都这样做要好得多。如果你真的关心性能,并且分析表明这是一个问题,你可以对传入的集合进行类检查,看看你是否可以避免复制。

于 2013-08-12T13:13:52.937 回答
0

这取决于 foo 在做什么。很可能它只是读取集合值,在这种情况下它不需要复制它,尤其是不可变的。

于 2013-08-12T13:29:11.940 回答
0

使用的一个优点ImmutableCollection是该方法保证它不会修改集合。但是那个保证只是给用户的,平台不理解,所以你还不如在评论或自定义注释中表达出来。

于 2013-08-12T13:30:34.973 回答