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,
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}
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)