我可以在 Java 8 中复制流吗?Java

2023-09-07 01:09:50 作者:啭裑╭落涙ァ

有时我想对流执行一组操作,然后使用其他操作以两种不同的方式处理生成的流.

Sometimes I want to perform a set of operations on a stream, and then process the resulting stream two different ways with other operations.

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

Can I do this without having to specify the common initial operations twice?

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

For example, I am hoping a dup() method such as the following exists:

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

推荐答案

一般情况下是不可能的.

It is not possible in general.

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

If you want to duplicate an input stream, or input iterator, you have two options:

假设您将一个流复制为两个流s1s2.如果您在 s1 中有高级 n1 元素,并且在 s2 中有 n2 元素,则必须保留 |n2- 内存中的 n1| 个元素,只是为了跟上步伐.如果您的流是无限的,则所需的存储空间可能没有上限.

Suppose you duplicate a stream into two streams s1 and s2. If you have advanced n1 elements in s1 and n2 elements with s2, you must keep |n2 - n1| elements in memory, just to keep pace. If your stream is infinite, there may be no upper bound for the storage required.

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

Take a look at Python's tee() to see what it takes:

此迭代工具可能需要大量辅助存储(取决于需要存储多少临时数据).一般来说,如果一个迭代器在另一个迭代器启动之前使用了大部分或全部数据,则使用 list() 而不是 tee() 会更快.

This itertool may require significant auxiliary storage (depending on how much temporary data needs to be stored). In general, if one iterator uses most or all of the data before another iterator starts, it is faster to use list() instead of tee().

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

要使此选项起作用,您可能需要访问流的内部工作原理.换句话说,生成器——创建元素的部分——应该首先支持复制.[OP:请参阅此 很好的答案,作为如何为问题中的示例]

B. When possible: Copy the state of the generator that creates the elements

Java 8 中的流 Stream

For this option to work, you'll probably need access to the inner workings of the stream. In other words, the generator - the part that creates the elements - should support copying in the first place. [OP: See this great answer, as an example of how this can be done for the example in the question]

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

It will not work on input from the user, since you'll have to copy the state of the entire "outside world". Java's Stream do not support copying, since it is designed to be as general as possible; for example, to work with files, network, keyboard, sensors, randomness etc. [OP: Another example is a stream that reads a temperature sensor on demand. It cannot be duplicated without storing a copy of the readings]

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

This is not only the case in Java; this is a general rule. You can see that std::istream in C++ only supports move semantics, not copy semantics ("copy constructor (deleted)"), for this reason (and others).