如果我正在编写.NET代码,我会经常将IEnumerable<T>
暴露在可能有意义的地方。也许这取决于LINQ和你可以使用foreach的事实,但它感觉&#34;正确&#34;这样做。
private List<String> _myList;
public IEnumerable<String> MyList
{
get { return _myList; }
}
现在我正在编写Java 8代码,我正在讨论是否应该尽可能以可能的方式公开Stream<T>
?也许是因为我必须打电话给Collection.stream()
,感觉它就像是工作&#34;,但它感觉不对?
private Collection<String> myCollection;
public Stream<String> getStuff() {
return myCollection.stream();
}
Stream<T>
是否意味着以与IEnumerable<T>
可能相同的方式在界面上公开?
答案 0 :(得分:5)
你问的是错误的问题。毕竟,支持两者并不困难,例如
Collection<Foo> getStuff();
default Stream<Foo> stuff() {
return getStuff().stream();
}
所以使用您的界面的代码不需要显式的stream()
调用,而interface
的实现者也不需要打扰它。
由于您始终通过Stream
或明确地公开Collection.stream()
支持,因此问题是您是否要公开Collection
。虽然为Stream
后端提供Collection
便宜,但从Collection
收集Stream
可能会变得很昂贵。
因此,暴露两种方式的接口表明它们同样可用,而对于不使用Collection
后端的实现,这些方法中的一种可能比另一种方法更昂贵。
因此,如果您确定所有实现(包括将来的实现)将始终使用(或必须支持)Collection
,那么通过API公开它可能会有用Collection
s支持某些Stream
没有的操作。如果您支持通过公开的Collection
修改基础数据,则尤其如此。
否则,仅支持Stream
访问可能是更好的选择。这使得实现可以自由地拥有除Collection
之外的其他后端。但是,这也意味着此API不支持Java 8之前的Java版本。
答案 1 :(得分:0)
您是否想成为Stream
自己,主要取决于您是否真的具有相应权力的Stream
,即支持并行化(并非所有Stream
都可以,但它是Stream
的众多好处之一,而且它是一个重要的好处之一。通常情况下,我宁愿成为Collection
并让我自己Stream
通过相应的API调用。
从[{1}}返回getStuff()
的{{1}}方法看起来正确。
答案 2 :(得分:0)
尽可能避免在接口中使用流。
流可能 *是有限的或无限的 *是顺序的或并行的 *可订购或不可订购 *是否需要关闭
接口的实现者和接口的客户端都无法知道应该(不)应用这些特征中的哪些,或者需要注意哪些特征。
在接口中选择最灵活的返回类型仅意味着客户要承担避免一切可能性的全部负担。通常,在接口中限制返回的数据类型会更加有用,以便实现者知道他们可以依靠哪些假设(出于相同的原因,在大多数情况下,返回Collection
本身不是很有用,返回更有用) List, Set, Iterable, InputStream
表示使用数据时客户的权利和义务。
并且当您需要更改返回数据的特征时,请更改接口,b故意断开客户端,以便他们可以将算法更新为更改的情况。
这比说:“我的方法返回一个Stream,所以现在我可以返回一个无限的流而不是一个有限的流,并且客户端代码仍然可以编译,太棒了!”有用。这不是很好,它是这样做的错误来源。客户端代码应该不继续通过这种剧烈的变化进行编译,因此使用明确说明close()
的无限性,并行性,有序性和义务的数据类型是一个更好的选择。
这样想:如果保持高度灵活性,那么Java7中所有返回List
或Set
或Queue
的接口都将返回Iterable
来保留灵活返回实际返回的数据类型。但这不是大多数接口返回的方法,而是返回一个Collection,告诉客户端他们可以安全地依赖size()方法,而返回Set则意味着它们可以安全地依赖非重复,例如。在界面上具有特定性和限制性不是罪过,而是一种美德。