我可以在 Java 8 中复制一个 Stream 吗?

新手上路,请多包涵

有时我想对一个流执行一组操作,然后用其他操作以两种不同的方式处理结果流。

我可以在不必指定两次公共初始操作的情况下执行此操作吗?

例如,我希望存在如下所示的 dup() 方法:

 Stream [] desired_streams = IntStream.range(1, 100).filter(n -> n % 2 == 0).dup();
Stream stream14 = desired_streams[0].filter(n -> n % 7 == 0); // multiples of 14
Stream stream10 = desired_streams[1].filter(n -> n % 5 == 0); // multiples of 10

原文由 necromancer 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 961
2 个回答

一般情况下是不可能的。

如果要复制输入流或输入迭代器,您有两种选择:

A. 将所有东西都保存在一个集合中,比如 List<>

假设您将一个流复制为两个流 s1s2 。 If you have advanced n1 elements in s1 and n2 elements with s2 , you must keep |n2 - n1| elements in记忆,只是为了跟上步伐。如果您的流是无限的,则所需存储空间可能没有上限。

看看 Python 的 tee() 看看它需要什么:

这个 itertool 可能需要大量的辅助存储(取决于需要存储多少临时数据)。通常,如果一个迭代器在另一个迭代器启动之前使用了大部分或全部数据,则使用 list()tee() 更快。

B. 如果可能:复制创建元素的生成器的状态

要使此选项起作用,您可能需要访问流的内部工作方式。换句话说,生成器——创建元素的部分——应该首先支持复制。 [OP:看到这个 很好的答案,作为如何为问题中的示例完成此操作的示例]

它不适用于用户的输入,因为您必须复制整个“外部世界”的状态。 Java的 Stream 不支持复制,因为它被设计得尽可能通用;例如,处理文件、网络、键盘、传感器、随机性等。[OP:另一个例子是按需读取温度传感器的流。如果不存储读数的副本,就无法复制]

不仅在 Java 中如此,在 Java 中也是如此。这是一般规则。您可以看到 C++ 中的 std::istream 仅支持移动语义,而不支持复制语义(“复制构造函数(已删除)”),出于这个原因(以及其他原因)。

原文由 Elazar 发布,翻译遵循 CC BY-SA 4.0 许可协议

不可能以这种方式复制流。但是,您可以通过将公共部分移动到方法或 lambda 表达式中来避免代码重复。

 Supplier<IntStream> supplier = () ->
    IntStream.range(1, 100).filter(n -> n % 2 == 0);
supplier.get().filter(...);
supplier.get().filter(...);

原文由 nosid 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题