按 ID 合并两个列表

Combine two lists by ID

我有两个对象列表,其内容如下所示:

List A
id = 1, name = "alex", height = null, weight = 60
id = 2, name = "sara", height = null, weight = 50

List B
id = 1, name = "alex", height = 40, weight = null
id = 2, name = "sara", height = 30, weight = null

我想不出任何好的方法来“合并”这两个覆盖空值的列表。理想的最终结果是:

id = 1, name = "alex", height = 40, weight = 60
id = 2, name = "sara", height = 30, weight = 50

我一直在研究 Kotlin 集合,看看是否有任何东西可以帮助我更接近这个,但我只能做到这一点:

a.union(b).groupBy { it.id }

这个 returns 一个以 ID 为键,完整对象为值的映射...但我仍然需要将这些值合并到一个对象中。

有没有什么不是非常手动的检查空值并在另一个列表中选择值的方法?

我做了以下(使用“用户”作为占位符。将其替换为您自己的数据结构):

List<User> ul1 = new ArrayList<>();
ul1.add(new User(1, "alex", null, 90));
ul1.add(new User(2, "sara", null, 50));

List<User> ul2 = new ArrayList<>();
ul2.add(new User(1, "alex", 40, null));
ul2.add(new User(2, "sara", 30, null));

List<User> rl = new ArrayList<>(Stream.concat(ul1.stream(), ul2.stream())
                                      .collect(Collectors.toMap(
                                              User::getId,
                                              e -> e,
                                              User::merge
                                      )).values());

for (User u : rl) {
    System.out.println(u.toString());
}

这是“用户”class(替换为您自己的数据结构):

public static class User {
    private final int id;
    private final String name;
    private final Integer height;
    private final Integer weight;

    public User(int id, String name, Integer height, Integer weight) {
        this.id = id;
        this.name = name;
        this.height = height;
        this.weight = weight;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public Integer getHeight() {
        return height;
    }

    public Integer getWeight() {
        return weight;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", height='" + height + '\'' +
                ", weight='" + weight + '\'' +
                '}';
    }

    public static User merge(User e1, User e2) {
        if (e1.id != e2.id)
            throw new IllegalArgumentException();

        return new User(
                e1.id,
                eval(e1.name, e2.name),
                eval(e1.height, e2.height),
                eval(e1.weight, e2.weight)
        );
    }

    private static <T> T eval(T v1, T v2) {
        return v1 != null ? v1 : v2;
    }
}

我得到的结果是:

User{id=1, name='alex', height='40', weight='90'}
User{id=2, name='sara', height='30', weight='50'}

所以我想它有效