简体   繁体   中英

Java Streams: Create Map Using Multiple List of different object types

I want to create a Map of objects using multiple lists of different object types. I want to take an example so that it'd be more clear and easy to discuss.

class Employee {
Long id;
String name;
// getters, setters, and toString
}

class Department {
Long id;
String name;
// getters, setters, and toString
} 

class EmployeeDepartment {
Long id;
Long employeeId;
Long deptId;
// getters, setters, and toString
}

class Subject {
Long id;
String name;
// getters, setters, and toString
}

class EmployeeSubject {
Long id;
Long employeeId;
Long subjectId;
// getters, setters, and toString
}

Now, I have

List<Employee> emplList;
List<EmployeeDepartment> emplDeptList;
List<EmployeeSubject> emplSubList;

I want to get a Map by which I can make a search of employee using: deptId, and subjectId

Something like

Map<List<Long, Long>, List<Employee>> deptSubToEmpMap;
// representing Map<List<deptId, subId>, List<empl>>

// Or
Map<Long, Map<Long, List<Employee>> deptToSubToEmpMap;
// representing Map<deptId, Map<subId, List<empl>>

or any other convenient form if it's better than above representation.

Note: I'm a newbie to Java Streams

You need to create EmployeeSubjectDepartment that will hold relation between employee, department and subject, as below,

@Getter@Setter
class EmployeeSubjectDepartment{
    Long empId;
    Long deptId;
    Long subId;

    public EmployeeSubjectDepartment(Long empId, Long deptId, Long subId) {
        this.empId = empId;
        this.deptId = deptId;
        this.subId = subId;
    }
}

And then merge emplDeptList and emplSubList to get emplyees

List<EmployeeSubjectDepartment> employeeSubjectDepartments = emplDeptList.stream()
                .flatMap(dept -> emplSubList.stream()
                        .filter(sub -> dept.employeeId.equals(sub.employeeId))
                        .map(sub -> new EmployeeSubjectDepartment(dept.employeeId, dept.deptId, sub.subjectId)))
                .collect(toList());

Map<Long, Map<Long, List<Long>>> result = employeeSubjectDepartments.stream()
        .collect(groupingBy(EmployeeSubjectDepartment::getDeptId,
                groupingBy(EmployeeSubjectDepartment::getSubId, mapping(e -> e.empId, toList()))));

This will result in Map with List of employeeIds.

If you want the List of employees, create EmployeeSubjectDepartment as below,

 class EmployeeSubjectDepartment{
        Employee emp;
        Long deptId;
        Long subId;
    } 

And then merge emplDeptList and emplSubList to get and map to emplyees from emplList

List<EmployeeSubjectDepartment> employeeSubjectDepartments = emplDeptList.stream()
                .flatMap(dept -> emplSubList.stream()
                        .filter(sub -> dept.employeeId.equals(sub.employeeId))
                        .map(sub -> new EmployeeSubjectDepartment(emplList.stream().filter(e -> e.id == sub.employeeId).findAny().orElse(null), dept.deptId, sub.subjectId)))
                .collect(toList());

Map<Long, Map<Long, List<Employee>>> result = employeeSubjectDepartments.stream()
        .collect(groupingBy(EmployeeSubjectDepartment::getDeptId,
                groupingBy(EmployeeSubjectDepartment::getSubId, mapping(e -> e.emp, toList()))));

This may not be a perfect solution but you can get the desired result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM