I have two lists of custom objects. And I want to merge both lists by id
, using Java 8.
I have a class Employee
with the fields (All String): id
, name
, city
.
And I have another class Person
with the fields (All String): id
, city
.
Here is an example :
List<Employee> employeeList = Stream.of(
new Employee("100","Alex",""),
new Employee("200","Rida",""),
new Employee("300","Ganga",""))
.collect(Collectors.toList());
List<Person> personList = Stream.of(
new Person("100","Atlanta"),
new Person("300","Boston"),
new Person("400","Pleasanton"))
.collect(Collectors.toList());
After merging the two lists I want to get the result shown below.
How can I do it?
List<Employee>
[
Employee(id=100, name=Alex, city=Atlanta),
Employee(id=200, name=Rida, city=null),
Employee(id=300, name=Ganga, city=Boston),
Employee(id=400, name=null, city=Pleasanton)
]
CodePudding user response:
Not sure if Employee class here extends Person. Ideally, it should.
An Employee can be a Person, but not all Person has to be an Employee. So, collecting it as a List<Employee>
makes no sense, due to this.
Ideally, you should collect it as a List<Person>
and Employee should extend Person. Please relook at your class structure instead of focusing on collecting it as List<Employee>
, that should solve your problem.
CodePudding user response:
you can use mapping and grouping from stream or search the second list by id and update the employee to the first list. Java does not include built-in functions that will automatically merge different objects
CodePudding user response:
In order to achieve that, firstly, you can create two maps based on the two lists using id
as a key.
Then create a stream over the key sets of these maps. Then inside the map()
operation you need to create a new Employee
object for every key by using passing a name
extracted from the employeeList
city
taken from the personById
.
When id
is not present in either of the maps the object returned by get()
will be null
and attempt to invoke method on it will triger the NullPointerException
. In order to handle this situation, we can make use of Null-object pattern, by defining two variables that could be safely accessed and will be provided as an argument to getOfDefault()
.
Then collect the stream element into a list with Collectors.toList()
.
Map<String, Employee> employeeById = employeeList.stream()
.collect(Collectors.toMap(Employee::getId, Function.identity()));
Map<String, Person> personById = employeeList.stream()
.collect(Collectors.toMap(Person::getId, Function.identity()));
Person nullPerson = new Person("", null); // null-object
Employee nullEmployee = new Employee("", null, null); // null-object
List<Employee> result = Stream.of(employeeById.keySet().stream(),
personById.keySet().stream())
.map(key -> new Employee(key,
employeeById.getOrDefault(key, nullEmployee).getName(),
personById.getOrDefault(key, nullPerson).getCity()))
.collect(Collectors.toList()); // or .toList() for Java 16