How to group by range of values in Java 8 using streams

前端 未结 2 755
没有蜡笔的小新
没有蜡笔的小新 2020-12-19 06:14

Here is a sample scenario:

Imagine we have employee records like:

name, age, salary (in 1000 dollars)
   a,  20,     50
   b,  22,     53
   c,  34,         


        
相关标签:
2条回答
  • 2020-12-19 06:39

    The below code should give you what you are looking for. The key is "Collectors" class which support grouping.

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

    The illustration assuming the salary is integer but easy to switch to double

    The complete program looks like

    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;
    
    }
    

    The output is

    {4.0=200, 2.0=100, 3.0=100}
    
    0 讨论(0)
  • 2020-12-19 06:44

    Yes, you could define an AgeGroup interface or even an enum like this (assuming Employee definition):

    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)
    
    0 讨论(0)
提交回复
热议问题