Iterable<T>
而不实现Collection<T>
。我正在实现一个需要定义一个接受Iterable<T>
参数的方法的接口,但是我用于支持此方法的对象需要一个Collection<T>
。这让我写了一些令人感觉很笨拙的代码,并在编译时产生了一些未经检查的警告。
public ImmutableMap<Integer, Optional<Site>> loadAll(
Iterable<? extends Integer> keys
) throws Exception {
Collection<Integer> _keys;
if (keys instanceof Collection) {
_keys = (Collection<Integer>) keys;
} else {
_keys = Lists.newArrayList(keys);
}
final List<Site> sitesById = siteDBDao.getSitesById(_keys);
// snip: convert the list to a map
将我的结果集更改为使用更通用的
Collection<? extends Integer>
类型并不能消除该行的未经检查的警告。此外,我无法将方法签名更改为接受Collection
而不是Iterable
,因为那样就不再覆盖超级方法,并且在需要时不会被调用。似乎没有办法解决这个强制转换或复制的问题:其他问题已经在这里和其他地方提出了,并且它似乎深深植根于Java的泛型和类型擦除系统中。但是我想问一下是否有任何可以实现
Iterable<T>
但不实现Collection<T>
的类?我已经浏览了Iterable
JavaDoc,并且我期望传递给我的接口的所有内容实际上都是集合。我想使用一个现成的类,因为它更有可能作为参数传递,并且可以使单元测试更有价值。我确定我编写的复制或转移位适用于我在项目中使用的类型,因为我正在编写一些单元测试。但是,我想为一些输入编写一个单元测试,这些输入是可迭代的但不是集合,到目前为止,我只能想到实现一个虚拟测试类来进行测试。
对于好奇的人,我正在实现的方法是Guava的CacheLoader<K, V>.loadAll(Iterable<? extends K> keys)
,支持方法是一个JDBI实例化数据访问对象,它需要一个集合作为@BindIn
接口的参数类型。我认为我的想法是离题了的,但以防万一有人想在我的问题上尝试横向思考。我知道我可以只需fork JDBI项目并重写@BindIn
注释以接受可迭代对象...
ServiceLoader
гҖӮ - aioobeLists.newArrayList
可以分配一个新数组,潜在地log(n)
次,因为它在分配支持数组之前不会得到大小。(尽管再次查看 Guava 代码,我意识到我的instanceof
然后转换是多余的。) - Patrick Mkeys
。如果这会破坏您的假设,则在所有情况下都应优先考虑复制。 - Brandon