【问题标题】:Collect/reduce on a stream when no combine function exists不存在组合功能时在流上收集/减少
【发布时间】:2017-02-18 06:16:06
【问题描述】:

我有一个集合,我想使用流 API 将其减少为单个值。看起来collectreduce 可以很好地工作,只是他们都想要一个combiner 对象来合并并行结果。就我而言,我没有组合操作。

流中不会有很多元素,所以我很高兴让它连续运行。有办法处理吗?

如果我的流包含 1,2 和 3,我想做相当于

result = new Foo().foo(1).foo(2).foo(3);

好像

result = stream.reduce(new Foo(),
                       (foo, ele) -> foo.foo(ele),
                       null);

可能会起作用,但在某些时候,一些更改(列表稍长,新的 Java 版本)combiner 将被调用并且会中断。

我返回的是不同的类型,所以reduce(BiFunction) 对我不起作用。

【问题讨论】:

  • 如果您担心流 API 会随心所欲地使用组合器,为什么不直接使用普通循环?
  • @shmosel 看起来确实可以解决问题。虽然它看起来也有点复杂,就像它试图解决语言引入的问题一样。
  • @AndyTurner 我可以这样做,尽管我目前正在喝 Kool-Aid,它说功能/流比程序/for 循环更好。我认为这通常更容易阅读。在另一个项目中,我使用了一个没有自动并行化功能的备用库 (javaslang),因此它有一个 reduce(initialElement, combiner) 方法,可以满足我的需要。
  • @TroyDaniels 我添加了一个答案,显示它在非流 Java 中是多么简单。有时你必须知道什么时候放下酷爱;)

标签: java java-stream


【解决方案1】:

我会在集合的元素上使用一个循环:

Foo result = new Foo();
for (int ele : collection) {
  result = result.foo(ele);
}

这很容易阅读,类似于流方法的冗长,您不必担心它的行为会因为 Streams 库中的黑暗巫术而意外改变。

【讨论】:

    【解决方案2】:

    如果您喜欢坚持使用流,您可以使用forEachOrdered,因为它可以是有状态的:

    AtomicReference<Foo> foo = new AtomicReference<>(new Foo());
    stream.forEachOrdered(ele -> foo.updateAndGet(f -> f.foo(ele)));        
    Foo result = foo.get();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-25
      • 2019-07-31
      • 2020-11-01
      • 1970-01-01
      • 2019-02-17
      • 1970-01-01
      • 2021-09-03
      相关资源
      最近更新 更多