如何在Java 8中使用流过滤两个列表对象并将值设置到新列表?

3
我将翻译以下内容:

我使用Java 8,有两个对象如下:

Person类:

public class Person {

    private String id;
    private String name;

    public Person() {
    }

    public Person(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

Person1类:

public class Person1 {
    private String id;
    private String name;

    public Person1() {
    }

    public Person1(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

I have two list look like :

 List<Person> persons= Arrays.asList(new Person("1","A"),new Person("2","B"));
  List<Person1> persons1 = Arrays.asList(new Person1("3","C"),new Person1("1","F"));

现在我想使用Java 8流循环两个列表并进行比较。如果列表中的任何一个对象与persons1相等,我将创建一个新列表并将其设置为新值。例如:如果Person1(“1”,“F”)等于Person(“1”,“A”),因为我使用id进行比较,我从Person1获取姓名并设置到Person上。结果:Person(“1,“F”)并将其添加到新列表中。

当我使用for循环时,我的代码如下:

 for (Person person : persons) {
            for (Person1 person1 : persons1 ) {
                if (person1.getId().equals(person.getId())) {
                    person.setName(person1.getId());
                    break;
                }
            }
        }

现在我想将它转换为具有新列表外观的流:
 List<Person> personList =
                list.stream()
                        .filter (
                                person -> list1.stream()
                                        .anyMatch(person1 -> person1.getId()== person.getId()))
                        .collect(Collectors.toList());

但它仅过滤人员。我想比较两个列表对象。如果ID相同,则将persons1对象中的名称设置为persons对象中的名称。我知道我们可以在Java 8流中使用映射,但我不知道如何做到这一点。请帮助


为什么你想在这里使用一个break? - Ravindra Ranwala
2个回答

5

有些任务使用流处理效果更佳,而其他任务则使用迭代处理方式更好。许多任务最好通过结合这两种方法来完成。在此解决方案中,使用流来构建映射表,然后使用迭代来更新匹配的人名。与您的解决方案相比,此解决方案具有线性时间复杂度。

Map<String, String> idToNameMap = persons1.stream()
    .collect(Collectors.toMap(Person1::getId, Person1::getName, (a, b) -> a));
for (Person person : persons) {
    if (idToNameMap.containsKey(person.getId())) {
        person.setName(idToNameMap.get(person.getId()));
    }
}

2
你可以使用 idToNameMap.containsKey(p.getId()) 替代 idToNameMap.get(p.getId()) != null。但是构造新的 Person 实例并不等同于修改现有对象。 - Holger
谢谢您的建议。我已经更新了答案。同时,我没有更新现有对象,因为这与函数式编程中的不可变性相矛盾。 - Ravindra Ranwala
2
那个矛盾是任务固有的。如果您假设对象是不可变的,那么也不需要构造新对象,因为persons1中的对象已经具有所需的属性,只需要进行过滤即可。 - Holger
非常感谢您。但我有一个问题:为什么我们需要参数:(a,b) -> a 因为当我尝试编写代码时: Map<String, String> idToNameMap = persons.stream() .collect(Collectors.toMap(Person1::getId, Person1::getName)); persons .stream() .filter(item -> idToNameMap.containsKey(item.getId())) .forEach(item -> item.setName(idToNameMap.get(item.getId()))); person.stream().forEach(System.out::println);它与您的结果相同。您能否向我解释一件事情? - trungitdn92
如果存在关键字冲突,它将使用合并函数来处理。但在您的情况下,由于不存在关键字冲突,因此它可以正常工作。 - Ravindra Ranwala
显示剩余5条评论

1

这不是最美的答案,但我想它会帮助你了解它是如何工作的。

List<Person> collect = persons.stream()
        .filter(person -> persons1.stream().anyMatch(person1 -> person1.getId() == person.getId()))
        .map(person -> {
            Person1 getted = persons1.stream()
                .filter(person1 -> person1.getId() == person.getId())
                .findAny()
                .orElseGet(null);
            if (getted == null) throw new IllegalStateException("Should be Impossible");
            person.setName(getted.getName());
            return person;
        })
        .collect(Collectors.toList());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接