流Java 8 api中是否有aggregateBy方法?

时间:2014-05-24 18:00:42

标签: java java-8 aggregation

在Brian Goetz的这个非常有趣但一岁的presentation中运行 - 在幻灯片链接中他提出了一个aggregateBy()方法,据说在Stream API中,它应该聚合列表的元素(?)到地图(给定默认初始值和操纵值的方法(对于重复键也是如此) - 请参阅演示文稿中的下一张幻灯片。)

显然Stream API中没有这样的方法。还有另一种方法可以在Java 8中做类似的事情吗?

3 个答案:

答案 0 :(得分:14)

可以使用Collectors类完成聚合操作。所以在视频中,示例等同于:

Map<String, Integer> map = 
    documents.stream().collect(Collectors.groupingBy(Document::getAuthor, Collectors.summingInt(Document::getPageCount)));

groupingBy方法会为您提供Map<String, List<Document>>。现在,您必须使用下游收集器来汇总与每个密钥关联的List中每个文档的所有页数。

这是通过向groupingBy提供summingInt的下游收集器来完成的,从而产生Map<String, Integer>

<小时/> 他们在文档中给出了基本相同的例子,他们计算了员工的总和。按部门划分的工资。

我认为他们删除了这个操作并创建了Collectors类,而不是让一个有用的类包含很多通常会使用的减少。

答案 1 :(得分:3)

我们假设我们有一份员工名单及其部门和薪水,我们希望每个部门支付的总薪水。

有几种方法可以执行此操作,例如,您可以使用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);
}

通常使用流,有几种方法可以获得所需的结果,例如:

import static java.util.stream.Collectors.*;

Map<String, Double> salaryByDepartment = persons.stream()
        .collect(groupingBy(Person::department, summingDouble(Person::salary)));

供参考,Person类:

static class Person {
  private final String name, department;
  private final double salary;
  public Person(String name, String department, double salary) {
    this.name = name;
    this.department = department;
    this.salary = salary;
  }
  public String name() { return name; }
  public String department() { return department; }
  public double salary() { return salary; }
}

答案 2 :(得分:1)

This particular Javadoc entry是关于Java 8中这个聚合的最接近的东西。即使它是第三方API,签名看起来也很好 - 你提供了一些函数来从中获取值,一些终值函数的值(在这种情况下为零),以及一些函数将函数和值组合在一起。

感觉很像Collector,它可以让我们做到这一点。

Map<String, Integer> strIntMap =
    intList.stream()
           .collect(Collectors
               .groupingBy(Document::getAuthor,
                Collectors.summingInt(Document::getPageCount)));

然后我们的想法是,我们将列表中每个条目的作者姓名分组,并将作者的总页码加到Map<String, Integer>中。