首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 8函数式编程中'reduce‘函数的第三个参数的用途

Java 8函数式编程中'reduce‘函数的第三个参数的用途
EN

Stack Overflow用户
提问于 2014-04-02 18:25:39
回答 3查看 10.5K关注 0票数 31

在什么情况下,Java 8 streams中调用了'reduce‘的第三个参数?

下面的代码尝试遍历字符串列表,并将每个字符串的第一个字符的代码点值相加。最后一个lambda返回的值似乎从未被使用过,如果您插入一个println,它似乎从未被调用过。文档描述它是一个‘组合器’,但我找不到更多细节……

代码语言:javascript
复制
int result =
  data.stream().reduce(0, (total,s) -> total + s.codePointAt(0), (a,b) -> 1000000); 
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-04-02 22:10:22

你是在说this function吗?

reduce U reduce(U单位,BiFunction累加器、BinaryOperator组合器)

使用提供的标识、累积和组合函数对此流的元素执行缩减。这相当于:

U result = identity;for (T element : this stream) result = accumulator.apply(result,element)返回结果;但不限于按顺序执行。标识值必须是组合器函数的标识。这意味着对于所有u,组合器(identity,u)等于u。此外,组合器函数必须与累加器函数兼容;对于所有u和t,必须满足以下条件:

combiner.apply(u,accumulator.apply(identity,t)) == accumulator.apply(u,t)这是一个终端操作。

API注意:使用这种形式的许多缩减可以更简单地由map和reduce操作的显式组合来表示。累加器函数充当融合的映射器和累加器,这有时可能比单独的映射和缩减更有效,例如,当知道以前减少的值可以避免一些计算时。类型参数:u-结果参数的类型: identity -合并器函数的标识值累加器-用于将附加元素合并到结果合并器中的关联、非干扰、无状态函数-用于组合两个值的关联、非干扰、无状态函数,必须与累加器函数兼容返回:缩减的结果另请参阅: reduce( BinaryOperator),reduce(Object,BinaryOperator)

我假设它的目的是允许并行计算,所以我猜测只有在并行执行缩减时才使用它。如果它是按顺序执行的,则不需要使用combiner。我不能确定这一点--我只是根据文档注释"...不被限制为按顺序执行“以及注释中提到的许多其他”并行执行“来猜测。

票数 18
EN

Stack Overflow用户

发布于 2014-09-24 17:29:09

我认为java.util.stream包摘要中的Reduction operations段落可以回答这个问题。让我在这里引用最重要的部分:

在其更一般的形式中,对产生<U>类型结果的<T>类型的元素执行reduce操作需要三个参数:

代码语言:javascript
复制
<U> U reduce(U identity,
              BiFunction<U, ? super T, U> accumulator,
              BinaryOperator<U> combiner);

在这里,identity元素既是约简的初始种子值,也是没有输入元素时的默认结果。累加器函数获取部分结果和下一个元素,并生成新的部分结果。组合器函数组合两个部分结果以产生新的部分结果。(在并行缩减中,合并器是必需的,其中输入被分区,为每个分区计算部分累加,然后合并部分结果以产生最终结果。)更正式地说,标识值必须是组合器函数的标识。这意味着对于所有ucombiner.apply(identity, u)等于u。此外,组合器函数必须是关联的,并且必须与累加器函数兼容:对于所有utcombiner.apply(u, accumulator.apply(identity, t))必须是equals() to accumulator.apply(u, t)

三参数形式是两参数形式的推广,将映射步骤合并到累加步骤中。我们可以使用更一般的形式重新转换简单的权重总和示例,如下所示:

代码语言:javascript
复制
 int sumOfWeights = widgets.stream()
                           .reduce(0,
                                   (sum, b) -> sum + b.getWeight())
                                   Integer::sum);

不过,显式的map-reduce形式更具可读性,因此通常应该首选。对于通过将映射和归约组合到单个函数中可以优化大量工作的情况,提供了广义形式。

换句话说,据我所知,三参数形式在两种情况下是有用的:

当并行执行matters.

  • When时,
  1. 可以通过组合映射和累加步骤来实现显着的性能优化。否则,可以使用更简单、更易读的显式map-reduce表单。

前面在同一文档中提到了显式形式:

代码语言:javascript
复制
int sumOfWeights = widgets.parallelStream()
        .filter(b -> b.getColor() == RED)
        .mapToInt(b -> b.getWeight())
        .sum();
票数 9
EN

Stack Overflow用户

发布于 2014-04-26 19:07:14

确认combiner用法的简单测试代码:

代码语言:javascript
复制
String[] strArray = {"abc", "mno", "xyz"};
List<String> strList = Arrays.asList(strArray);

System.out.println("stream test");
int streamResult = strList.stream().reduce(
        0, 
        (total,s) -> { System.out.println("accumulator: total[" + total + "] s[" + s + "] s.codePointAt(0)[" + s.codePointAt(0) + "]"); return total + s.codePointAt(0); }, 
        (a,b) -> { System.out.println("combiner: a[" + a + "] b[" + b + "]"); return 1000000;}
    );
System.out.println("streamResult: " + streamResult);

System.out.println("parallelStream test");
int parallelStreamResult = strList.parallelStream().reduce(
        0, 
        (total,s) -> { System.out.println("accumulator: total[" + total + "] s[" + s + "] s.codePointAt(0)[" + s.codePointAt(0) + "]"); return total + s.codePointAt(0); }, 
        (a,b) -> { System.out.println("combiner: a[" + a + "] b[" + b + "]"); return 1000000;}
    );
System.out.println("parallelStreamResult: " + parallelStreamResult);

System.out.println("parallelStream test2");
int parallelStreamResult2 = strList.parallelStream().reduce(
        0, 
        (total,s) -> { System.out.println("accumulator: total[" + total + "] s[" + s + "] s.codePointAt(0)[" + s.codePointAt(0) + "]"); return total + s.codePointAt(0); }, 
        (a,b) -> { System.out.println("combiner: a[" + a + "] b[" + b + "] a+b[" + (a+b) + "]"); return a+b;}
    );
System.out.println("parallelStreamResult2: " + parallelStreamResult2);

输出:

代码语言:javascript
复制
stream test
accumulator: total[0] s[abc] s.codePointAt(0)[97]
accumulator: total[97] s[mno] s.codePointAt(0)[109]
accumulator: total[206] s[xyz] s.codePointAt(0)[120]
streamResult: 326
parallelStream test
accumulator: total[0] s[mno] s.codePointAt(0)[109]
accumulator: total[0] s[abc] s.codePointAt(0)[97]
accumulator: total[0] s[xyz] s.codePointAt(0)[120]
combiner: a[109] b[120]
combiner: a[97] b[1000000]
parallelStreamResult: 1000000
parallelStream test2
accumulator: total[0] s[mno] s.codePointAt(0)[109]
accumulator: total[0] s[xyz] s.codePointAt(0)[120]
accumulator: total[0] s[abc] s.codePointAt(0)[97]
combiner: a[109] b[120] a+b[229]
combiner: a[97] b[229] a+b[326]
parallelStreamResult2: 326
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22808485

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档