Java8 Stream reduce 归约的并发注意事项。combiner.apply(u, accumulator.apply(identity, t))理解

reduce概念

下面解释是抄别人的。和haskell等语言里的概念很像

好的命名是自解释的 reduce的方法取得就是其中归纳的含义 java8 流相关的操作中,我们把它理解
“累加器”,之所以加引号是因为他并不仅仅是加法 他的运算可以是一个Lambda 表达式 所以更准确的说 reduce 是一个迭代运算器
Stream包的文档中其实已经说的很明白了 但是就是因为不是很理解所以看的云里雾里 其中说到:
一个reduce操作(也称为折叠)接受一系列的输入元素,并通过重复应用操作将它们组合成一个简单的结果

并发的问题

函数介绍

  • reduce(accumulator)
  • reduce(identity,accumulator)
  • reduce(identity,accumulator,combiner)
    identityreduce进行迭代操作的初始值。accumulator是用来迭代的。combiner是并发时用来合并各线程结果的。

代码

public class AppTest {
    /**
     * Rigorous Test :-)
     */
    @Test
    public void test2() {
        assertTrue(true);
        int b = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).parallel().reduce(0, (acc, x) -> acc + x);
        int c = Stream.of(2, 3, 4, 5, 6, 7, 8, 9).parallel().reduce(1, (acc, x) -> acc + x);
        int d = Stream.of(2, 3, 4, 5, 6, 7, 8, 9).parallel().reduce(1, (acc, x) -> acc + x, (x, y) -> x + y - 1);
        System.out.printf("初始值个数不影响结果:%d\n", b);
        System.out.printf("无修正:%d\n", c);
        System.out.printf("合并修正:%d\n", d);
    }
}

结果

在这里插入图片描述


可以明显看到第二个方式是有问题的。原因是初始值加了四遍。这是由于他内部是使用了fork-join框架 把大任务转小任务,然后并发运行。有点像归并排序的感觉。但是为了保证并发安全,他把每个输入数据都复制了一份,这样自然不用🔓了,但同时导致初始值多加三遍。所以redue源代码注释里才会有这句话。

combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)

和这句话

combiner(identity, u) is equal to u

这两句话只要满足一个就行了。
在这个例子里,初始值为0当然是符合的,为1 是不符合的。

我们这里可以把思维再扩展些。这里的等于并不是要求地址相等是同一个对象,而只是要求逻辑上等价

话说这也太卷了,我就做个累加也要并发。😃

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
list.stream().map().reduce()是一种常见的使用流(Stream)进行数据处理的方式。在这个例子中,通过使用map()方法将流中的元素映射为另一种类型,然后使用reduce()方法对映射后的元素进行聚合操作。 在引用\[1\]的代码中,有几个使用了map()和reduce()的例子。首先,通过list.stream().reduce((x, y) -> x + y)可以求得整数集合的元素之和。这里的reduce()方法接受一个BinaryOperator函数作为参数,用于将流中的元素进行累加操作。 另外,通过list.stream().reduce((x, y) -> x * y)可以求得整数集合的元素之积。这里的reduce()方法同样接受一个BinaryOperator函数作为参数,用于将流中的元素进行累乘操作。 最后,通过list.stream().reduce((x, y) -> x > y ? x : y)可以求得整数集合的最大值。这里的reduce()方法同样接受一个BinaryOperator函数作为参数,用于比较流中的元素并返回较大的值。 综上所述,list.stream().map().reduce()可以用于对流中的元素进行映射和聚合操作,可以根据具体需求选择不同的映射和聚合函数来实现不同的功能。 #### 引用[.reference_title] - *1* [Java8 Stream详解~归(reduce)](https://blog.csdn.net/gqltt/article/details/123141263)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Strame--流操作](https://blog.csdn.net/zgz102928/article/details/124400625)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值