I have a class Employee which has a tree structure with property team
public class Employee {
private String name;
private List<Employee> team;
}
Using Java lambdas I need to flat this tree into same level list while converting Employee class into the following ConvertedEmployee while storing names in dedicated lead
and subordinates
properties. So ConvertedEmployee is in some sense a node which keeps parent and children. And I need to have a list of those.
public class ConvertedEmployee {
private String name;
private String lead;
private List<String> subordinatesNames;
}
So final result should be List<ConvertedEmployee>
I was thinking to use recursion here.
But I can only flat the tree and can't rebuild it's parents.
EDIT:
Input is instance of Employee object that basically has a tree inside team
CodePudding user response:
A non-recursive solution using concatenation of the streams followed by filtering out the "duplicated" entries which do not have lead
field set:
public static List<ConvertedEmployee> convert(List<Employee> staff) {
return staff
.stream()
.flatMap(e -> Stream.concat(
// subordinates of current employee
e.getTeam()
.stream()
.map(sub -> new ConvertedEmployee(
sub.getName(), e.getName(),
sub.getTeam().stream().map(Employee::getName).collect(Collectors.toList())
)),
// current employee by themself
Stream.of(new ConvertedEmployee(
e.getName(), null,
e.getTeam().stream().map(Employee::getName).collect(Collectors.toList())
))
))
.collect(Collectors.collectingAndThen(
Collectors.toMap(
ConvertedEmployee::getName,
c -> c,
(e1, e2) -> e1.getLead() != null ? e1 : e2.getLead() != null ? e2 : e1,
LinkedHashMap::new
),
map -> new ArrayList<>(map.values())
));
}
Test for the following setup:
Employee intern = new Employee("intern", Collections.emptyList());
Employee junior = new Employee("junior", Collections.emptyList());
Employee middleDev = new Employee("mid", Arrays.asList(junior));
Employee devOps = new Employee("devOps", Collections.emptyList());
Employee teamLead = new Employee("teamLead", Arrays.asList(intern, middleDev));
Employee pm = new Employee("mgr", Arrays.asList(teamLead, devOps));
List<Employee> staff = Arrays.asList(intern, junior, middleDev, devOps, teamLead, pm);
convert(staff).forEach(System.out::println);
Output:
ConvertedEmployee(name=intern, lead=teamLead, subordinatesNames=[])
ConvertedEmployee(name=junior, lead=mid, subordinatesNames=[])
ConvertedEmployee(name=mid, lead=teamLead, subordinatesNames=[junior])
ConvertedEmployee(name=devOps, lead=mgr, subordinatesNames=[])
ConvertedEmployee(name=teamLead, lead=mgr, subordinatesNames=[intern, mid])
ConvertedEmployee(name=mgr, lead=null, subordinatesNames=[teamLead, devOps])