以不同的方法将操作附加到Stream是不好的做法?

Lui*_*uel 3 java java-8 java-stream

假设我的应用程序中有多个类使用的方法.此方法将a Stream作为参数并应用终端操作forEach以将数据写入文件,如下所示:

public File writeStreamToTempFile(Stream stream) {
    stream.forEach(item -> {
        //some code to write item to a file
    }
}
Run Code Online (Sandbox Code Playgroud)

这个方法有多个调用者,在某些方法中我需要转换数据,比方说使用map函数,如下所示:

public void exportAnimalsData() {
    Stream<Animal> animalStream = //fetch data from a DB
    animals.filter(a -> a.type.equals("dog"))
           .map(a -> //Do something useful to transform the Dogs);

    writeStreamToTempFile(animalStream);
}
Run Code Online (Sandbox Code Playgroud)

并非该writeStreamToTempFile方法的所有调用者都需要对流执行其他操作.

所以我的问题是:

将操作应用于不同方法的流是不好的做法?

我在某地读过Stream永远不应该是方法的返回类型(调用者不知道该方法是否已经消耗了流),它是否也适用于方法的参数?

我应该只应用相同方法中所需的所有操作,还是可以在不同的方法中将中间操作附加到同一个流中?

jbx*_*jbx 8

我在某处读过Stream永远不应该是方法的返回类型

不知道你在哪里读到a Stream永远不应该是方法的返回类型.(你能用链接更新你的问题吗?).

相反,Stream API的设计者之一Brian Goetz显然不这么认为:

/sf/answers/1727582181/

(调用者不知道该方法是否已经消耗了流)

如果调用者正在获取Stream它,则隐含地理解该流是可用的.如果你返回一个消耗Stream,就像返回一个关闭Socket或关闭InputStream.虽然可能在语法上,但它只是糟糕的编码.这并不意味着你不应该返回SocketInputStream从方法只是因为一些不好的编码器偶尔会返回一个状态不佳.

相反,monadic样式对象旨在返回.Stream,Optional,CompletableFuture,和所有的功能接口(Function,Consumer,Operator等等)都旨在被返回,使得更多的功能样式的操作可以被连接到它们,而不当场实际执行的功能.

你发布给我的例子非常合理.您可以通过对管道的其他操作来装饰Stream.您可以使用逻辑来决定将哪些操作添加到管道中,并且没有理由不在小方法中正确封装它们.

此外,如果流非常大,携带数十万个元素,如果你返回了一个集合,你只需要在内存中创建一个巨大的集合,产生所有成本的成本,然后再将它们再次流式化以将它们写入文件.没有多大意义吗?

  • 有兴趣看到它.但它可能是错误的(或上下文不同).请放心,返回"Stream"(或任何其他功能类型)完全没问题.只需使您的代码可读且组织清晰. (3认同)