聚合操作如何在Java流上运行? [英] How do aggregate operations work on Java streams?

查看:123
本文介绍了聚合操作如何在Java流上运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下摘录自汇总操作中的Java教程,我们将人的姓名映射到他们的性别。

In the following excerpt from the Java tutorials in aggregate operations, we map the names of the people to their sexes.

Map<Person.Sex, List<String>> namesByGender =
roster
    .stream()
    .collect(
        Collectors.groupingBy(
            Person::getGender,                      
            Collectors.mapping(
                Person::getName,
                Collectors.toList())));

我理解收集操作:

1)将每个人分组getGender的结果流。

2)将每个Person映射到getName的结果。

3)从结果中形成一个列表。

4生成一个Map,其键是Persons的性别,其数据值是Persons的名称。

I understand that the collect operation:
1) Groups each Person in the stream by the result of getGender.
2) Maps each Person to the result of getName.
3) Forms a list from the results and.
4) Generates a Map whose keys are the Persons' genders and whose data values are the Persons' names.

我的问题是:

1)收藏家的行为顺序是什么?

2)什么是间歇类型他们之间?

My questions are:
1) In what order do the Collectors act?
2) What are the intermittent types between them?

推荐答案

收藏家不会行动,因此不会在订单中行事。它不像一个收集器在使用间歇类型将其传递给另一个数据之前处理所有数据。

The Collectors do not "act", hence do not act in an order. It’s not like one Collector processes all data before passing it to another using an intermittent type.

您正在与这些工厂组合一个收集器,当传递给 Stream.collect 时,它将立即完成整个工作。

You are composing a single Collector with these factories, which will do the entire work at once when being passed to Stream.collect.

因为 收集器的文档 interface 解释:

As the documentation of the Collector interface explains:


收集器由四个函数指定,这四个函数协同工作以将条目累积为可变结果容器,并可选择对结果执行最终转换。它们是:

A Collector is specified by four functions that work together to accumulate entries into a mutable result container, and optionally perform a final transform on the result. They are:


  • 创建新的结果容器(供应商())

  • 合并新的数据元素到结果容器(accumulator())

  • 将两个结果容器合并为一个(组合器())

  • 执行可选的最终转换容器(终结者())

  • creation of a new result container (supplier())
  • incorporating a new data element into a result container (accumulator())
  • combining two result containers into one (combiner())
  • performing an optional final transform on the container (finisher())

所以 toList() collector可以像 ArrayList :: new 一样简单实现为供应商, List :: add 作为累加器和 List :: addAll 作为组合器,不需要自定义的整理器,这是它在参考实现中的确实实现方式,但这是一个实现细节,其他实现是允许。

So the toList() collector can be implemented as simple as ArrayList::new as supplier, List::add as accumulator and List::addAll as combiner, not needing a custom finisher, which is how it is indeed implemented in the reference implementation, but that’s an implementation detail, other implementations are allowed.

然后, Collectors.mapping 是compo使用指定的下游收集器来唱新的收集器,并通过首先应用指定的映射器函数并将其结果传递给原始累加器函数来装饰它的累加器函数。结果又是一个由四个函数组成的收集器。在收集操作期间,映射器函数将在添加到列表之前应用于每个元素。

Then, Collectors.mapping is composing a new collector using the specified downstream collector and decorating it’s accumulator function by applying the specified mapper function first and passing its result to the original accumulator function. The result is again a collector consisting of four functions. During the collect operation, the mapper function will be applied for each element right before adding to the list.

最后, Collectors.groupingBy 会做更复杂的构图。供应商将创建一个新地图,通常为 HashMap 。累加器将评估您的分组功能,并使用 Map.computeIfAbsent 之类的操作将结果存储到地图中,这将评估下游收集器的供应商是否键是新的,然后应用下游收集器的累加器函数,它是您的场景中的组合函数。组合器函数在 Map.merge 上使用map的值(如果只有一个包含密钥)或使用下游的组合器(如果存在密钥)结算在两个映射中。

Finally, Collectors.groupingBy will do a much more complex composition. The supplier will create a new map, typically HashMap. The accumulator will evaluate your grouping function and store the result into the map, using an operation like Map.computeIfAbsent which will evaluate the downstream collector’s supplier if the key is new, followed by applying the downstream collector’s accumulator function, which is the composed function in your scenario. The combiner function settles on Map.merge using either map’s value if only one contains a key or using the downstream’s combiner if a key is present in both maps.

因此,组合收集器的处理包括对指定函数的交错处理,而不是一个接一个地处理一个收集器。换句话说,对于顺序执行,操作将等同于

So the processing of a composed collector consists of an interleaved processing of the specified functions rather than processing one collector after the other. In other words, for a sequential execution, the operation will be equivalent to

Map<Person.Sex, List<String>> namesByGender = new HashMap<>();
for(Person p: roster)
    namesByGender.computeIfAbsent(p.getGender(), k -> new ArrayList()).add(p.getName());

这篇关于聚合操作如何在Java流上运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆