簡體   English   中英

Java 8:按Id合並兩個包含對象的List

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM