流Java8API中是否有aggregateBy方法?
在Brian Goetz的这张非常有趣但只有一岁的幻灯片中,他展示了一个流API中的流Java8API中是否有aggregateBy方法?,java,java-8,aggregation,Java,Java 8,Aggregation,在Brian Goetz的这张非常有趣但只有一岁的幻灯片中,他展示了一个流API中的aggregateBy()方法,该方法应该将列表(?)的元素聚合到一个映射(给定一个默认初始值和一个操作该值的方法(也适用于重复键)-请参阅演示文稿中的下一张幻灯片) 显然,世界上没有这样的方法。在Java 8中有没有其他类似的方法?假设我们有一个员工列表,其中包含他们的部门和工资,我们需要每个部门支付的总工资 有几种方法可以做到这一点,例如,您可以使用toMap收集器来聚合每个部门的数据: 第一个参数是关键映
aggregateBy()
方法,该方法应该将列表(?)的元素聚合到一个映射(给定一个默认初始值和一个操作该值的方法(也适用于重复键)-请参阅演示文稿中的下一张幻灯片)
显然,世界上没有这样的方法。在Java 8中有没有其他类似的方法?假设我们有一个员工列表,其中包含他们的部门和工资,我们需要每个部门支付的总工资 有几种方法可以做到这一点,例如,您可以使用
toMap
收集器来聚合每个部门的数据:
- 第一个参数是关键映射器(聚合轴=部门)
- 第二个是值映射器(要聚合的数据=薪水),以及
- 第三个是合并函数(聚合数据的方式=对值求和)
import static java.util.stream.Collectors.*;
public static void main(String[] args) {
List<Person> persons = Arrays.asList(new Person("John", "Sales", 10000),
new Person("Helena", "Sales", 10000),
new Person("Somebody", "Marketing", 15000));
Map<String, Double> salaryByDepartment = persons.stream()
.collect(toMap(Person::department, Person::salary, (s1, s2) -> s1 + s2));
System.out.println("salary by department = " + salaryByDepartment);
}
聚合操作可以使用类来完成。因此,在视频中,示例相当于:
Map<String, Integer> map =
documents.stream().collect(Collectors.groupingBy(Document::getAuthor, Collectors.summingInt(Document::getPageCount)));
Map=
documents.stream().collect(Collectors.groupingBy(Document::getAuthor,Collectors.summingit(Document::getPageCount));
groupingBy
方法将为您提供一个Map
。现在,您必须使用下游收集器对列表中与每个键关联的每个文档的所有页数求和
这是通过向groupingBy
提供一个下游收集器来实现的,它是summingit
,从而生成一个映射
他们在文档中给出了基本相同的示例,其中他们计算了各部门员工的工资总额
我认为他们删除了这个操作并创建了收集器类,而不是创建了一个有用的类,它包含了许多您通常会使用的缩减。是我在Java 8中找到的最接近这个聚合的东西。尽管它是第三方API,但签名似乎排列得很好——您提供了一些函数从中获取值,一些值的终端函数(在本例中为零),以及一些将函数和值组合在一起的函数
这感觉很像一个,这将使我们有能力做到这一点
Map<String, Integer> strIntMap =
intList.stream()
.collect(Collectors
.groupingBy(Document::getAuthor,
Collectors.summingInt(Document::getPageCount)));
Map strIntMap=
intList.stream()
.收藏(收藏家)
.groupingBy(文档::getAuthor,
Collectors.summingit(Document::getPageCount));
然后,我们将列表中每个条目的作者姓名分组,并将作者的总页码加在一张地图+1中,这是一个很好的问题;非常非常有启发性。事实上,收集器
不仅有助于聚合;你也有一些基本的东西,比如Collectors.toList()
等等;从长远来看,所有这些操作都在同一个“功能包”中可能会变得相当混乱。我想JDK可以使用一个Aggregates
class…@fge也许Brian Goetz会看到这个线程并解释rational,这会很有趣。是的,aggregateBy()是对现在包含在收集器中的概念的早期尝试。(虽然我认为所引用的示例早在一年多前就出现了。)aggregateBy()的一个问题是,它只进入了“一级深度”。Collectors.groupingBy()通过“下游”收集器解决了这一问题,并且更具可组合性。@BrianGoetz OK,现在我看到了收集器
界面,所有这些都在收集器
中是有道理的,但是我的话,理解这个界面背后的概念需要时间!我想对收集器接口的解释才是真正的答案question@fge那将是一个更长的解释!但要坚持下去,这是值得的。一旦你掌握了概念,它就会非常强大。
Map<String, Integer> map =
documents.stream().collect(Collectors.groupingBy(Document::getAuthor, Collectors.summingInt(Document::getPageCount)));
Map<String, Integer> strIntMap =
intList.stream()
.collect(Collectors
.groupingBy(Document::getAuthor,
Collectors.summingInt(Document::getPageCount)));