Collect/reduce on a stream when no combine function exists
我有一个集合,我想在其中使用流API将其减少为单个值。看起来collect或reduce可以很好地工作,只是他们两个都希望combiner对象合并并行结果。就我而言,我没有合并操作。
流中不会有很多元素,所以我很高兴能够串行运行。有办法解决吗?
如果我的流包含1,2和3,我想做等价于
1
| result = new Foo().foo(1).foo(2).foo(3); |
似乎
1 2 3
| result = stream.reduce(new Foo(),
(foo, ele) -> foo.foo(ele),
null); |
可能会起作用,但是在某些时候,将调用combiner的某些更改(列表稍长,新的Java版本),并且将中断。
我返回的是其他类型,所以reduce(BiFunction)对我不起作用。
- 是否可以通过字段列表检索地图内部的java8流样式的重复项?
-
如果您担心在流API的使用上一时兴起,那么为什么不只使用普通循环呢?
-
@shmosel看起来确实可以解决问题。尽管它看起来也有些复杂,但是它正在尝试解决该语言引入的问题。
-
@AndyTurner我可以做到这一点,尽管我目前正在喝Kool-Aid,它说功能/流比过程/ for循环要好。我认为通常更容易阅读。在另一个项目上,我使用了一个不具有自动并行化功能的备用库(javaslang),因此,它具有一个reduce(initialElement,Combiner)方法,该方法可以满足我的需要。
-
@TroyDaniels我添加了一个答案,以显示在非流Java中它是如此简单。有时,您必须知道何时放下库尔援助;)
-
有几种方法可以解决此问题,但是没有一种方法比for循环更简单。当然,这与以下事实有关:即使result = stream.reduce(new Foo(), (foo, ele) -> foo.foo(ele), null);也不比简单的循环简单,并且添加修复程序并不会使它更简单……顺便说一句,即使null组合器不流,它们也会拒绝null组合器不要用它。
我只会在集合的元素上使用一个循环:
1 2 3 4
| Foo result = new Foo();
for (int ele : collection) {
result = result.foo(ele);
} |
这很容易理解,具有与streams方法类似的冗长性,并且您不必担心由于Streams库中的黑暗伏都教徒,其行为会意外地发生变化。
如果您希望坚持使用流,则可以使用forEachOrdered,因为它可以保持状态:
1 2 3
| AtomicReference<Foo> foo = new AtomicReference<>(new Foo());
stream.forEachOrdered(ele -> foo.updateAndGet(f -> f.foo(ele)));
Foo result = foo.get(); |