首页 > 解决方案 > 根据其他列表中的匹配对象更新列表中两个对象的属性

问题描述

我有两个 Pojo:

class Object1 {

    public Object1(String id) {
        this.id = id;
    }

    private String id;
    private Integer value1;
    private Integer value2;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Integer getValue1() {
        return value1;
    }

    public void setValue1(Integer value1) {
        this.value1 = value1;
    }

    public Integer getValue2() {
        return value2;
    }

    public void setValue2(Integer value2) {
        this.value2 = value2;
    }
}
public class Object2 {

    private String id;
    private Integer value;

    public Object2(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Integer getValue() {
        return value;
    }

    public void setValue(Integer value) {
        this.value = value;
    }
}

我有两个这些对象的列表,其中对象具有相同的 ID。我想通过设置两个对象的 ID 匹配的 object2 值字段中的值,根据 l2 中对象的值来设置列表 l1 中对象的 value2。

import java.util.Arrays;
import java.util.List;

public class Main{

    public static void main(String[] args) {

        Object1  o1_1 = new Object1("asdf");
        Object1 o1_2 = new Object1("qwert");
        List<Object1> l1 = Arrays.asList(o1_1, o1_2);

        Object2  o2_1 = new Object2("asdf");
        o2_1.setValue(123);
        Object2 o2_2 = new Object2("qwert");
        o2_2.setValue(456);
        List<Object2> l2 = Arrays.asList(o2_1, o2_2);


        l1.forEach(object1 -> l2.stream()
                .filter(object2 -> object1.getId().equals(object2.getId()))
                .forEach(object2 -> object1.setValue2(object2.getValue())));

    }
}

我将如何使用 java 流 API 有效地做到这一点?

这个解决方案正确吗?复杂度是 O(n²) 对吧?有没有更有效的方法?

标签: javajava-stream

解决方案


如果您关心性能,可以将其中一个列表转换为以 ID 为键的查找映射,然后更新另一个列表。它的复杂度为 O(N)。

您将像这样创建一个查找地图:

Map<Integer, Object2> map = new HashMap<>();
for (Object2 obj : l2) {
    map.put(obj.getId(), obj);
}

或使用流:

Map<Integer, Object2> map = l2.stream()
      .collect(Collectors.toMap(Object2::getId, obj -> obj));

现在您可以在地图的帮助下遍历第一个列表并使用值更新元素。

l1.stream().forEach(o1 -> o1.setValue2(map.get(o1.getId()).getValue()));

或者,如果Object2只有idand value,您甚至可以创建一个map<id, value>

Map<Integer, String> map = new HashMap<>();
for (Object2 obj : list) {
    map.put(obj.getId(), obj.getValue());
}

l1.stream().forEach(o1 -> o1.setValue2(map.get(o1.getId())));

推荐阅读