我想迭代2个列表来更新1中的值。以下是我尝试使用嵌套for循环的简化版本。
注释掉的代码是我尝试使用流的代码。假设姓氏是唯一的。我将在实际代码中比较的值实际上是唯一的。
如果有人能指出我正确的方向,我将不胜感激。
List<Person> list1 = new ArrayList<>();
List<Person> list2 = new ArrayList<>();
list1.add(new Person("Jane", "Doe"));
list1.add(new Person("John", "Smith"));
list2.add(new Person("", "Doe"));
list2.add(new Person("", "Smith"));
for (Person p1 : list1) {
for (Person p2 : list2) {
if (p1.getLastName().equals(p2.getLastName())) {
p2.setFirstName(p1.getFirstName());
break;
}
}
}
System.out.println(list2.toString());
//list1.stream()
// .filter(e -> (list2.stream()
// .filter(d -> d.getLastName()
// .equals(e.getLastName()))
答案 0 :(得分:2)
您可以创建<lastName, firstName>
地图并使用它来更新第二个列表:
Map<String, String> lastNameMap = list1.stream()
.collect(Collectors.toMap(Person::getLastName, Person::getFirstName));
list2.stream().forEach(p -> p.setFirstName(lastNameMap.get(p.getLastName())));
请注意,这假设没有重复的姓氏,任何重复的姓氏都可能导致混淆。
由于collect
调用是在上面写的,它会在重复的lastName
值上失败,并且可能应保持原样,以便错误可以防止姓氏/名字混淆。< / p>
答案 1 :(得分:2)
经典for
循环似乎是最佳选择。 Stream
解决方案如下:
list1.forEach(p1 ->
list2.stream().filter(p2 -> p1.getLastName().equals(p2.getLastName()))
.findFirst()
.ifPresent(p2 -> p2.setFirstName(p1.getFirstName())));
答案 2 :(得分:1)
这是另一种方法:
list1.forEach(p1 -> list2.stream()
.filter(p2 -> p1.getLastName().equals(p2.getLastName()))
.findFirst()
.ifPresent(p2 -> p2.setFirstName(p1.getFirstName()))
);
或:
list1.forEach(p1 -> list2.stream()
.filter(p2 -> p1.getLastName().equals(p2.getLastName()))
.limit(1)
.forEach(p2 -> p2.setFirstName(p1.getFirstName()))
);
答案 3 :(得分:0)
由于你想用流来解决你的问题,我想你想深入研究函数式编程。如果是这种情况,我建议您退后一步,尝试将函数式编程的基本原理内化,这样您就可以开始使用函数式编程 mindset 来解决这样的问题。在这种特定情况下,这意味着:不要更新您的数据结构到位,而是返回一个更新值的新实例(对于您的列表和您的人员实体,保持为true)并避免运行有效的代码块。始终从操作中返回有意义的值。
考虑到这一点,我建议采用以下方法:
final List<Person> combined = list1.stream()
.flatMap(p1 -> list2.stream().filter(p2 -> p2.lastname().equals(p1.lastName())).map(p2 -> new Person(p1.firstName(), p2.lastName())))
.collect(Collectors.toList())
也许你可以把它作为一个起点。