[英]Java 8: merging two Lists containing objects by Id
我有 2 個列表:
// 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);
有誰知道如何將這兩個列表合並為一個列表,其中包含兩個列表中的所有員工,按“PersonalNumber”分組並保持新列表中元素的順序? newList 來自具有預定義排序的數據庫,我需要保持這種方式,所以我無法在 Java 端再次排序
結果應該是:
[
{"123", "new_name1", NEW},
{"123", "old_name1", OLD},
{"456", "new_name2", NEW},
{"456", "old_name1", OLD},
]
我保證兩個列表的大小相同,並且包含具有相同個人編號的員工。 我只想用相同的personalNumber“注入”新員工下的每個老員工
您可以這樣做:正如您提到的,兩個列表具有相同的PersonalNumber ,因此您可以使用此屬性進行分組。 為了確保基於personalNumber
的順序,我使用了LinkedHashMap
。
Stream.concat(newList.stream(), oldList.stream())
.collect(Collectors.groupingBy(Employee::getPersonalNumber,
LinkedHashMap::new, Collectors.toList()))
.values().stream().flatMap(List::stream)
.collect(Collectors.toList());
注意:如果兩個輸入流都是有序的,則stream#concat
的結果是有序的。
Collections 排序應該適用於此。
newList.addAll(oldList);
Collections.sort(newList, Comparator.comparing(Employee::getPersonalNumber) );
關鍵是,“這種排序保證是穩定的:相同的元素不會因為排序而被重新排序。”
由於無法對新列表進行排序,我認為這意味着您不知道新列表的順序。 你可以用 ol' N^2 方法來做。
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?
}
你可以這樣做:
// Sort oldList on personalNumber for faster access when retrieving the records
// with same personalNumber
oldList.sort(Comparator.comparing(Employee::getPersonalNumber));
List<Employee> result = new ArrayList<Employee>();
for (int i = 0; i < newList.size(); i++) {
// Get an employee, `e` from `newList` and add to `result`
Employee e = newList.get(i);
result.add(e);
// Add elements from `newList` to `result` until a different `personalNumber`
// occurs
while (i < newList.size() - 1 && e.getPersonalNumber().equals(newList.get(i + 1).getPersonalNumber())) {
result.add(newList.get(++i));
}
// Iterate `oldList` to find an employee with the `personalNumber` equal to that
// of `e`
int j;
boolean found = false;
for (j = 0; j < oldList.size(); j++) {
if (oldList.get(j).getPersonalNumber().equals(e.getPersonalNumber())) {
found = true;
break;
}
}
// If `oldList` has an employee with the `personalNumber` equal to that of `e` ,
// add elements from `oldList` to `result` until a different `personalNumber`
// occurs. Note that `oldList` has already been sorted.
if (found) {
result.add(oldList.get(j));
while (j < oldList.size() - 1 && oldList.get(++j).getPersonalNumber().equals(e.getPersonalNumber())) {
result.add(oldList.get(j));
}
}
}
演示:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
enum Status {
OLD, NEW;
}
class Employee {
private String name;
private String personalNumber;
private Status status;
public Employee() {
super();
}
public Employee(String name, String personalNumber, Status status) {
this.name = name;
this.personalNumber = personalNumber;
this.status = status;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPersonalNumber() {
return personalNumber;
}
public void setPersonalNumber(String personalNumber) {
this.personalNumber = personalNumber;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
@Override
public String toString() {
return personalNumber + ", " + name + ", " + status;
}
}
public class Main {
public static void main(String[] args) {
// old list
List<Employee> oldList = new ArrayList<Employee>();
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);
// Sort oldList on personalNumber for faster access when retrieving the records
// with same personalNumber
oldList.sort(Comparator.comparing(Employee::getPersonalNumber));
List<Employee> result = new ArrayList<Employee>();
for (int i = 0; i < newList.size(); i++) {
// Get an employee, `e` from `newList` and add to `result`
Employee e = newList.get(i);
result.add(e);
// Add elements from `newList` to `result` until a different `personalNumber`
// occurs
while (i < newList.size() - 1 && e.getPersonalNumber().equals(newList.get(i + 1).getPersonalNumber())) {
result.add(newList.get(++i));
}
// Iterate `oldList` to find an employee with the `personalNumber` equal to that
// of `e`
int j;
boolean found = false;
for (j = 0; j < oldList.size(); j++) {
if (oldList.get(j).getPersonalNumber().equals(e.getPersonalNumber())) {
found = true;
break;
}
}
// If `oldList` has an employee with the `personalNumber` equal to that of `e` ,
// add elements from `oldList` to `result` until a different `personalNumber`
// occurs. Note that `oldList` has already been sorted.
if (found) {
result.add(oldList.get(j));
while (j < oldList.size() - 1 && oldList.get(++j).getPersonalNumber().equals(e.getPersonalNumber())) {
result.add(oldList.get(j));
}
}
}
// Display the result
result.forEach(System.out::println);
}
}
Output:
123, new_name1, NEW
123, old_name1, OLD
456, new_name2, NEW
456, old_name2, OLD
這是 Java 流和 InsStream 的另一種方法
private List<Employee> mergeLists(List<Employee> oldList, List<Employee> newList) {
return IntStream.range(0, oldList.size())
.mapToObj(index -> Arrays.asList(newList.get(index), oldList.get(index)))
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
這種方法是可能的,因為
我保證兩個列表的大小相同,並且包含具有相同個人編號的員工。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.