如何使用Java 8中的流按值范围分组

9
以下是一个示例场景:
假设我们有员工记录,如下所示:
name, age, salary (in 1000 dollars)
   a,  20,     50
   b,  22,     53
   c,  34,     79

等等。目标是计算不同年龄组(例如21到30岁,31到40岁等)的平均工资。

我想使用stream完成这个任务,但我无法理解如何使用groupingBy来完成这个任务。我在考虑可能需要定义某种元组年龄范围。有任何想法吗?

2个回答

14

以下代码应该可以给你想要的结果。关键是"Collectors"类,它支持分组。

Map<Double,Integer> ageGroup= employees.stream().collect(Collectors.groupingBy(e->Math.ceil(e.age/10.0),Collectors.summingInt(e->e.salary)));

这个示例假设薪水是整数,但很容易转换为双精度浮点数。

完整的程序看起来像:

public static void main(String[] args) {
    // TODO Auto-generated method stub

    List<Employee> employees = new ArrayList<>();
    employees.add(new Employee("a",20,100));
    employees.add(new Employee("a",21,100));
    employees.add(new Employee("a",35,100));
    employees.add(new Employee("a",32,100));


    Map<Double,Integer> ageGroup= employees.stream().collect(Collectors.groupingBy(e->Math.ceil(e.age/10.0),Collectors.summingInt(e->e.salary)));
    System.out.println(ageGroup);
}

public static class Employee {
    public Employee(String name, int age, int salary) {
        super();
        this.name = name;
        this.age = age;
        this.salary = salary;
    }
    public String name;
    public int age;
    public int salary;

}

输出为

{4.0=200, 2.0=100, 3.0=100}

5

是的,你可以定义一个AgeGroup接口或者一个enum,像这样(假设已经定义了Employee):

enum AgeGroup {
    TWENTIES,
    THIRTIES,
    FORTIES,
    FIFTIES;
    .....
}
Function<Employee, AgeGroup> employee2Group = e -> {
    if(e.age >= 20 && e.getAge() < 30)
        return AgeGroup.TWENTIES;
    ....
    return null;
};

Map<AgeGroup, Double> avgByAgeGroup = employees.stream()
    .collect(Collectors.groupingBy(employee2Group, Collectors.averagingInt(Employee::getSalary)));

avgByAgeGroup.get(AgeGroup.TWENTIES)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接