我想复制一个Java8流,这样我可以处理它两次。我可以收集
作为一个列表,并从中获取新的流;
// doSomething() returns a stream
List<A> thing = doSomething().collect(toList());
thing.stream()... // do stuff
thing.stream()... // do other stuff
但我认为应该有一种更有效/优雅的方式。
有没有办法复制流而不把它变成集合?
我实际上正在处理一个
既
的流,所以想在移动到右侧投影并以另一种方式处理之前,先以一种方式处理左侧投影。有点像这样(到目前为止,我被迫使用toList
技巧)。
List<Either<Pair<A, Throwable>, A>> results = doSomething().collect(toList());
Stream<Pair<A, Throwable>> failures = results.stream().flatMap(either -> either.left());
failures.forEach(failure -> ... );
Stream<A> successes = results.stream().flatMap(either -> either.right());
successes.forEach(success -> ... );
使用供应商
为每个终止操作生成流。
Supplier<Stream<Integer>> streamSupplier = () -> list.stream();
每当需要该集合的流时,请使用streamSupplier。get()
以获取新流。
例子:
streamSupplier。get()。anyMatch(谓词)
您可以将局部变量与供应商一起使用,以设置流管道的公共部分。
从…起http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/:
重用流
Java 8流不能被重用。一旦调用任何终端操作,流即关闭:
Stream<String> stream = Stream.of("d2", "a2", "b1", "b3", "c")
.filter(s -> s.startsWith("a"));
stream.anyMatch(s -> true); // ok
stream.noneMatch(s -> true); // exception
Calling `noneMatch` after `anyMatch` on the same stream results in the following exception:
java.lang.IllegalStateException: stream has already been operated upon or closed
at
java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:229)
at
java.util.stream.ReferencePipeline.noneMatch(ReferencePipeline.java:459)
at com.winterbe.java8.Streams5.test7(Streams5.java:38)
at com.winterbe.java8.Streams5.main(Streams5.java:28)
为了克服这一限制,我们必须为我们想要执行的每个终端操作创建一个新的流链,例如,我们可以创建一个流供应商来构建一个新的流,其中所有中间操作都已设置:
Supplier<Stream<String>> streamSupplier =
() -> Stream.of("d2", "a2", "b1", "b3", "c")
.filter(s -> s.startsWith("a"));
streamSupplier.get().anyMatch(s -> true); // ok
streamSupplier.get().noneMatch(s -> true); // ok
对get()
的每次调用都会构造一个新的流,我们将保存该流以调用所需的终端操作。
我认为你对效率的假设有点倒退。如果你只使用一次数据,你会得到巨大的效率回报,因为你不必存储它,流给你强大的“循环融合”优化,让你在管道中高效地流动整个数据。
如果您想重复使用相同的数据,那么根据定义,您要么生成两次(确定性地)数据,要么存储它。如果它已经在一个集合中,那就太好了;然后迭代两次是很便宜的。
我们用“分叉流”进行了设计实验。我们发现,支持这一点有实际成本;它以牺牲不常见的情况为代价,加重了常见情况(使用一次)的负担。最大的问题是处理“当两个管道不以相同的速度消耗数据时会发生什么”不管怎样,现在你又回到缓冲了。这是一个显然没有分量的功能。
如果要重复操作同一数据,请将其存储,或将操作构造为使用者,然后执行以下操作:
stream()...stuff....forEach(e -> { consumerA(e); consumerB(e); });
您还可以查看RxJava库,因为它的处理模型更适合这种“流分叉”。
我想复制一个Java 8流,这样我可以处理它两次。我可以作为列表并从中获取新流; 但我觉得应该有一个更高效/更优雅的方法。 有没有一种方法可以复制流而不将其变成集合? 我实际上正在处理一个流,所以在移动到右侧投影并以另一种方式处理之前,希望先以一种方式处理左侧投影。类似于这样(到目前为止,我不得不使用技巧)。
问题内容: 我想复制一个Java 8流,以便可以处理两次。我可以collect列出并从中获得新的信息流; 但我认为应该有一种更有效/更优雅的方法。 有没有一种方法可以复制流而不将其转换为集合? 我实际上正在使用 流,因此想先处理左侧投影,然后再移至右侧投影并以另一种方式处理。有点像这样(到目前为止,我被迫使用这种技巧)。 问题答案: 你可以将局部变量与一起使用,以设置流管道的公共部分。 从http
方法是 现在我试着像这样改成stream,但我不知道这种改是否正确: 如何避免出现例外,解决问题? 我应该以某种方式重构代码吗?
下面是我的代码: 从下面的函数调用上面的函数: 我不知道为什么。
问题内容: 我正在尝试使用Stream API生成Order实例。我有一个创建订单的工厂函数,并且使用DoubleStream初始化订单金额。 如果我使用文字(1.0)初始化Order实例,则可以正常工作。当我使用doubleStream创建随机数量时,将引发异常。 问题答案: 答案在(重点是我的)的javadoc中: 流仅应操作一次(调用中间流或终端流操作) 。例如,这排除了“分叉”流,其中相同