繁体   English   中英

方法返回Stream是否安全 <T> ?

[英]Is it safe for a method to return a Stream<T>?

我有一种情况,我正在读取数据库并返回List<String> ,其中每个字符串都被选中并根据某些条件添加到列表中。 方法签名是:

public List<String> myMethod(String query, int limit)

第二个参数提供返回列表大小的limit=-1 (设置limit=-1将删除任何大小限制)。 为了避免使这个方法占用大量内存,我编写了一个返回Stream<String>而不是list的等效方法。 注意:我不需要随机访问返回的元素或任何其他特定于列表的功能。

但是,我对返回Stream<>有点怀疑,特别是因为该方法是公开的。 使用Java返回Stream<>的公共方法是否安全?

它不仅安全,而且是Java首席架构师推荐的。

特别是如果您的数据是基于I / O的,因此在调用myMethod内存中尚未实现,那么返回Stream而不是List是非常明智的。 客户端可能只需要使用它的一部分或将其聚合成一些固定大小的数据。 因此,您有机会从O(n)内存需求转到O(1)。

请注意,如果并行化对于您的用例也是一个有趣的想法,那么建议您使用自定义分裂器,其分割策略适应I / O数据源的顺序性质。 在这种情况下,我可以推荐一个的博客文章,它提出了这样一个分裂者。

我相信默认情况下,你应该在公共方法接口中避免使用Stream,因为它们很容易使用,请参阅如何在没有isFinite()和isOrdered()方法的情况下安全地使用Java Streams?

基本上,调用方法并获取流的客户端必须确保当方法实现更改返回流的特性时,它们的算法不会中断(或者在集成测试中断)。 这是一件非常困难的事情(因为流特性很容易忘记)并且很容易忘记。

因此,如果您返回的数据尚未实现,并且您希望将其留给客户决定如何实现,我甚至只会将Stream视为返回值。 但即便如此,Iterable或Iterator似乎也是更好的选择,因为它们没有流中不必要的并行处理包,并且防御性编程需要防范。

例如,当返回List时,您的客户端知道返回的数据类型是有限的并且是有序的,并且迭代它并不会令人惊讶地在ForkJoinPool上并行运行可能会破坏整个应用程序。 使用Stream,您必须调用sequential()来防范这种可能性。

如果数据源需要在消费后关闭,我宁愿使用InputStream的变体而不是Stream,因为实现者会很好地记住他们需要关闭流(而静态检查器会提醒他们)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM