首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有3个参数的Java8 stream.reduce() --获得透明度

具有3个参数的Java8 stream.reduce() --获得透明度
EN

Stack Overflow用户
提问于 2015-05-03 15:58:57
回答 2查看 4.5K关注 0票数 8

我编写这段代码是为了将单词列表缩减为以'A‘开头的单词数量的长计数。我编写它只是为了学习Java 8,所以我想更好地理解它:我意识到这可能不是编写这段代码的最佳方式;它只是为了实践!

代码语言:javascript
运行
复制
Long countOfAWords = results.stream().reduce(
    0L,
    (a, b) -> b.charAt(0) == 'A' ? a + 1 : a,
    Long::sum);

中间参数/lambda(称为累加器)似乎能够在没有最后的'Combiner‘参数的情况下减少完整的列表。事实上,Javadoc实际上说:

{@code累加器}函数充当一个融合映射器和累加器,*它有时比单独的映射和还原更有效,例如当知道以前的约简值时,可以避免*某些计算。

作者的编辑-下面的陈述是错误的,所以不要让它迷惑你;我只是把它保存在这里,这样我就不会破坏原来答案的上下文。

无论如何,我可以推断,累加器必须输出组合器组合的1和0。不过,从文档中我并没有发现这一点特别明显。

我的问题

有没有办法在组合器执行之前查看输出,这样我就可以看到组合器组合的1和0的列表了吗?这将有助于调试更复杂的情况,我相信我最终会遇到这种情况。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-05-03 16:15:19

组合器不会减少0和1的列表。当流不是并行运行时,在这种情况下不使用它,因此下面的循环是等价的:

代码语言:javascript
运行
复制
U result = identity;
for (T element : this stream)
    result = accumulator.apply(result, element)
return result;

当您并行运行流时,任务会跨成多个线程。因此,例如,管道中的数据被划分为独立评估和生成结果的块。然后,组合器用于合并这个结果。

因此,您将不会看到减少的列表,而是两个值--标识值或由任务之和计算的另一个值。例如,如果您在组合器中添加了一个print语句

代码语言:javascript
运行
复制
(i1, i2) -> {System.out.println("Merging: "+i1+"-"+i2); return i1+i2;}); 

你可以看到这样的东西:

代码语言:javascript
运行
复制
Merging: 0-0
Merging: 0-0
Merging: 1-0
Merging: 1-0
Merging: 1-1

这将有助于调试更复杂的情况,我肯定会遇到这样的情况。

更普遍的情况是,如果您想查看go管道上的数据,可以使用peek (或者调试器也可以帮助)。因此,适用于您的示例:

代码语言:javascript
运行
复制
long countOfAWords = result.stream().map(s -> s.charAt(0) == 'A' ? 1 : 0).peek(System.out::print).mapToLong(l -> l).sum();

它可以输出:

代码语言:javascript
运行
复制
100100

免责声明:我意识到这可能不是编写这段代码的最佳方式,这只是为了实践!

完成任务的惯用方法是对流进行filter,然后简单地使用count

代码语言:javascript
运行
复制
long countOfAWords = result.stream().filter(s -> s.charAt(0) == 'A').count();

希望能有所帮助!)

票数 12
EN

Stack Overflow用户

发布于 2015-05-03 16:14:53

查看正在发生的事情的一种方法是将方法引用Long::sum替换为包含println的lambda。

代码语言:javascript
运行
复制
List<String> results = Arrays.asList("A", "B", "A", "A", "C", "A", "A");
Long countOfAWords = results.stream().reduce(
        0L,
        (a, b) -> b.charAt(0) == 'A' ? a + 1 : a,
        (a, b) -> {
            System.out.println(a + " " + b);
            return Long.sum(a, b);
        });

在这种情况下,我们可以看到组合器并没有被实际使用。这是因为流不是平行的。我们真正要做的就是使用累加器将每个String与当前的Long结果连续组合;从来没有两个Long值被组合。

如果将stream替换为parallelStream,则可以看到使用了组合器,并查看了它组合的值。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30015971

复制
相关文章

相似问题

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