mmsr :
I have this requirement of transforming a List of Objects into List of grouped objects of different type.
public class Person {
private String name;
private String dept;
private int amount;
//constructors
//getters and setters
}
public class GroupedPersons {
private String dept;
private int sumAmount;
private List<Person> personsOfDept;
// how should be the constructor??
//getters and setters
}
List<Person> persons = Arrays.asList(
new Person("Mark", "Sales", 100),
new Person("Rob", "Marketing", 200),
new Person("Kyle", "Sales", 150),
new Person("Jack", "Accounts", 50),
new Person("Sam", "Sales", 150),
new Person("Jeff", "Marketing", 200));
I need the result as
List<GroupedPersons>
["Sales",400,List<Person>]
["Marketing",400,List<Person>]
["Accounts",50,List<Person>]
I tried
Map<String,List<Person>> deptMap = persons.stream().collect(Collectors.groupingBy(Person::getDept));
But unable to reduce the map to the List of object I need.
Fullstack Guy :
We can use a constructor for the GroupedPersons
class that will take the dept
, sumAmount
and personsOfDept
list, like so:
class GroupedPersons {
private String dept;
private int sumAmount;
private List<Person> personsOfDept;
public GroupedPersons(String dept, int sumAmount, List<Person> personsOfDept) {
this.dept = dept;
this.sumAmount = sumAmount;
this.personsOfDept = personsOfDept;
}
}
Then we can use the the following logic to first get the grouping done by dept
of the Person
which will result in a Map<String, List<Person>>
and then using the stream from the entrySet().stream()
of the map to sum the amount
and get the List<Person>
from the Map.Entry<String, List<Person>>.getValue()
:
List<GroupedPersons> list = persons.stream()
.collect(Collectors.groupingBy(p -> p.getDept()))
.entrySet()
.stream()
.map(ent -> new GroupedPersons(
ent.getKey(),
ent.getValue().stream().mapToInt(p -> p.getAmount()).sum(),
ent.getValue()))
.collect(Collectors.toList());