Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8: merging two Lists containing objects by Id

I have 2 Lists:


// old list
List<Employee> oldList = new ArrayList<>();
Employee emp1 = new Employee();
emp1.setPersonalNumber("123");
emp1.setName("old_name1");
emp1.setStatus(Status.OLD);

Employee emp2 = new Employee();
emp2.setPersonalNumber("456");
emp2.setName("old_name2");
emp2.setStatus(Status.OLD);

oldList.add(emp1);
oldList.add(emp2);

// new list
List<Employee> newList = new ArrayList<>();
Employee newEmp1 = new Employee();
newEmp1.setPersonalNumber("123");
newEmp1.setName("new_name1");
newEmp1.setStatus(Status.NEW);

Employee newEmp2 = new Employee();
newEmp2.setPersonalNumber("456");
newEmp2.setName("new_name2");
newEmp2.setStatus(Status.NEW);

newList.add(newEmp1);
newList.add(newEmp2);

Does anyone know how can I merge those 2 Lists to one List containing all the employees from both lists grouped by "PersonalNumber" and keeping the order of the elemets in newList? newList comes from the Database with a predefined sorting, and I need to keep it that way, so I can't sort it again on the Java side

Result should be:

[
    {"123", "new_name1", NEW},
    {"123", "old_name1", OLD},
    {"456", "new_name2", NEW},
    {"456", "old_name1", OLD},
]

I have the guarantee that both lists have the same size and contain employees with the same personalNumbers. I just want to "inject" each old employee under the new employee with the same personalNumber

like image 449
Cambiasso Avatar asked Mar 03 '23 10:03

Cambiasso


2 Answers

You can do like this: As you mentioned that both lists have the same PersonalNumber so you can group by using this property. To ensure order based on the personalNumber, I've used LinkedHashMap.

Stream.concat(newList.stream(), oldList.stream())
            .collect(Collectors.groupingBy(Employee::getPersonalNumber,
                    LinkedHashMap::new, Collectors.toList()))
            .values().stream().flatMap(List::stream)
            .collect(Collectors.toList());

Note: The result of stream#concat is ordered if both of the input streams are ordered.

like image 155
Hadi J Avatar answered Mar 05 '23 19:03

Hadi J


Collections to sort should work for this.

newList.addAll(oldList);
Collections.sort(newList, Comparator.comparing(Employee::getPersonalNumber) );

The key is that, "This sort is guaranteed to be stable: equal elements will not be reordered as a result of the sort."

Since cannot sort the new list, I take that to mean you don't know the order of the new list. You can do it the ol' N^2 method.

for(int i = 0; i<newList.size(); i+=2){
    String newNum = newList.get(i).getPersonalNumber();
    Employee old = oldList.stream().filter(
          emp->newNum.equals(
              emp.getPersonalNumber()
          )
        ).findFirst().orElse(null);
    newList.add(i+1, old);
    oldList.remove(old); //not nescessary?
}
like image 33
matt Avatar answered Mar 05 '23 17:03

matt