如何流式传输2个列表&修改1

时间:2018-06-17 14:15:47

标签: lambda java-8 java-stream

我想迭代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()))

4 个答案:

答案 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())

也许你可以把它作为一个起点。