Using Map to get an object list from 2 different object lists

Viewed 46

I have 2 List:

List<Employee> employees = List.of(
                new Employee(1, "Bob", 3),
                new Employee(2, "Nick", 1),
                new Employee(3, "Tim", 2)
        );

List<Company> companies = List.of(
                new Company(1, "Facebook"),
                new Company(2, "Google"),
                new Company(3, "Tesla")
        );

With 3 class:

class Employee {
        private Integer id;
        private String name;
        private Integer companyId;
}

class Company {
        private Integer id;
        private String name;
}

class EmployeeCompany {
        private Integer employeeId;
        private String employeeName;
        private Integer companyId;
        private String companyName;
}

And i have class EmployeeCompany with information of both employee and corresponding company.

I have to use Map to get a EmployeeCompany List from employees and companies:

[
   {
       employeeId: 1,
       employeeName: "Bob",
       companyId: 3,
       companyName: "Tesla"
   },
   {
       employeeId: 2,
       employeeName: "Nick",
       companyId: 1,
       companyName: "Facebook"
   },
   {
       employeeId: 3,
       employeeName: "Tim",
       companyId: 2,
       companyName: "Google"
   }
]

I have to use Map not map of Stream

2 Answers

I have to use Map

You don't need one.

Create a constructor / method accepting both to create a new object

class EmployeeCompany { 
    public EmployeeCompany(Employee e, Company c) {
        this.employeeId = e.getId();
        // TODO
    } 
} 

Create at least one method for cross referencing the lists

private static Optional<Company> findCompany(int id, List<Company> companies) {
    return companies.stream().filter(c -> c.getId() == id).findFirst();
}

Iterate one list, and join against the other

List<EmployeeCompany> ec = employees.stream().map(e -> {
    Company c = findCompany(companies, e.getCompanyId()).get();
    return new EmployeeCompany(e, c);
}).collect(toList());

Starting with a Map<Integer, String> companies would be simpler

By simply putting in the appropriate constructors and setters of your classes you can do it as follows:

  • Iterate thru the list of employees
  • Then iterate thru the list of companies.
  • when you find the company id that matches the current employee's company you simply create a new EmployeeCompany instance and place it in the list.
  • if no match is found, the employee entry is ignored.
List<EmployeeCompany> result = new ArrayList<>();
for (Employee emp : employees) {
    for(Company com : companies) {
        if (com.getId() == emp.getCompanyId()) {
            result.add(new EmployeeCompany(emp.getId(),emp.getName(), com.getId(),
                    com.getName()));
        
            break;
        }
    }
    // if this is reached, then no match was found.  Additional
    // code could be placed here to print an informatory message.
}

for(EmployeeCompany ec : result) {
    System.out.println(ec);
}

prints

{EmployeeId=1, EmployeeName=Bob, CompanyId=3, CompanyName=Tesla}
{EmployeeId=2, EmployeeName=Nick, CompanyId=1, CompanyName=Facebook}
{EmployeeId=3, EmployeeName=Tim, CompanyId=2, CompanyName=Google}

Here is the toString() override I used for the EmployeeCompany class. It can be altered as required.

public String toString() {
    return String.format("{EmployeeId=%s, EmployeeName=%s, CompanyId=%s, CompanyName=%s}",
          employeeId, employeeName, companyId, companyName);
}
Related