Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 方法返回流是否安全<;T>;?_Java_Java 8_Java Stream - Fatal编程技术网

Java 方法返回流是否安全<;T>;?

Java 方法返回流是否安全<;T>;?,java,java-8,java-stream,Java,Java 8,Java Stream,我有这样一种情况:我正在读取数据库并返回一个列表,其中每个字符串都被选中并根据某些条件添加到列表中。方法签名为: public List<String> myMethod(String query, int limit) 公共列表myMethod(字符串查询,整数限制) 第二个参数提供了返回列表大小的上限(设置limit=-1将删除任何大小限制)。为了避免这个方法占用大量内存,我编写了一个等价的方法,它返回Stream,而不是列表。(注意:我不需要随机访问返回的元素或任何其他特定

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

public List<String> myMethod(String query, int limit)
公共列表myMethod(字符串查询,整数限制)
第二个参数提供了返回列表大小的上限(设置
limit=-1
将删除任何大小限制)。为了避免这个方法占用大量内存,我编写了一个等价的方法,它返回
Stream
,而不是列表。(注意:我不需要随机访问返回的元素或任何其他特定于列表的功能。)


然而,对于返回
,我有点怀疑,尤其是因为该方法是公开的。在Java中使用公共方法返回
安全吗?

不仅安全,而且由首席Java架构师负责

特别是如果您的数据是基于I/O的,因此在调用
myMethod
时尚未在内存中具体化,则最好返回流而不是列表。客户机可能只需要使用其中的一部分,或者将其聚合为一些固定大小的数据。因此,您有机会从O(n)内存需求转到O(1)


请注意,如果并行化对您的用例来说也是一个有趣的想法,那么建议您使用自定义拆分器,其拆分策略适合于I/O数据源的顺序性质。在这种情况下,我可以推荐使用这种拆分器的方法。

我认为默认情况下,您应该避免在公共方法接口中使用流,因为使用它们很危险,请参阅

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

<>所以,如果你返回的数据还没有被具体化,你想把流当作返回值,你想把它留给你的客户来决定如何实现。但即便如此,Iterable或迭代器似乎是更好的选择,因为它们没有流所具有的不必要的并行处理负担,而防御性编程需要加以防范

例如,当返回一个列表时,您的客户机知道返回的数据类型是有限的和有序的,对它的迭代不会意外地在ForkJoinPool上并行运行,可能会破坏整个应用程序。对于Stream,您必须调用
sequential()
,以防止这种可能性


如果数据源在使用后需要关闭,我更喜欢使用流上的
InputStream
,因为实现者会清楚地记得他们需要关闭流(静态检查器会提醒他们)。

在某些情况下,返回Iterable/迭代器会更清晰、更容易。我经常在代码中构建一个
迭代器。从
迭代器中生成
非常困难。@OldCurmudgeon如果您返回
,您几乎可以免费获得
迭代器(
Stream.Iterator()
)@Marko-同意-但是如果您提供一个简单的适配器来流式处理Java 8中的
迭代器
,您仍然可以向后兼容Java 7和更早版本。@OldCurmudgeon
迭代器
不可关闭
,这会给支持I/O的迭代器带来相当多的麻烦。似乎与此类似,并感谢您链接到布赖恩·戈茨的回答。我对安全性还有一个疑问:在公共方法中返回
,这意味着我无法确保它将被关闭。我注意到上面说“几乎所有流实例在使用后实际上都不需要关闭”,但无法找到有关可疑单词“几乎”的更多详细信息。@ChthonicProject很简单:如果流有I/O资源支持,那么它肯定需要关闭。这是您必须做出的选择——急切地将所有内容复制到堆上,释放I/O资源,或者拥有一个需要关闭的流。但我认为,有一种方法可以安全地将I/O支持的流转换为堆上列表,这很简单;另一个方向是不可能的。因此,您只需遵循流程即可增加灵活性。没有注意到Javadoc中同一段落后面的重要句子。在这里分享,以传播喜悦:“如果流确实需要关闭,可以在try-with-resources语句中将其声明为资源。这与您的评论(当然还有主要答案)一起,结束了我所有的疑问和犹豫。是的,流是
自动关闭的