如何从具有公共字段的另一个对象列表中为一个对象列表的字段设置值?

Kar*_*mal 1 java java-8 java-stream

我有 2 个列表,比方说

1 -> List<Employee> list1;
2 -> List<Age> list2

class Employee {
    String name;
    String age;
    String address;
}

class Age {
    String name;
    String age;
}
Run Code Online (Sandbox Code Playgroud)

我喜欢做的是我需要更换的年龄在所有记录员工列表随着年龄的年龄列表具有相同名称的两个。我如何在 Java 8 中实现这一目标?

Nik*_*las 5

您可以List<Age>在迭代以下项目的内部流式传输List<Employee>

list1.forEach(e -> e.setAge(
     list2.stream()                                     // Stream<Age>
          .filter(a -> a.getName().equals(e.getName())) // ... find the name match
          .map(Age::getAge)                             // ... extract the age
          .findAny().orElse("unknown")));               // ... return it or else "unknown"
Run Code Online (Sandbox Code Playgroud)
  • 如果没有找到匹配的名称,则默认值设置为unknown
  • 此外,您必须确保没有基于年龄的重复名称。
  • 年龄是String- 可以吗?
  • 你确定没有null值吗?

如果你想消除这种不匹配的项目,我建议你使用,而IteratorMap<String, List<Age>>

Map<String, List<Age>> map = list2.stream()
    .collect(Collectors.groupingBy(             // Map<String, List<Age>>
         Age::getName));                        // ... where 'name' is the key

final  Iterator<Employee> iterator = list1.iterator();
while (iterator.hasNext()) {                    // Iterating List<Employee>
    final Employee e = iterator.next();         // Employee
    if (map.containsKey(e.getName())) {         // If there is Age with equal 'name'
        final String age = map.get(e.getName()) // ... get the first found age
            .get(0).getAge();
        e.setAge(age);                          // ... set it to the Employee
    } else iterator.remove();                   // ... or else remove the Employee
}
Run Code Online (Sandbox Code Playgroud)

再次关心我上面列出的要点。此外,如果您不想使用 first found age map.get(e.getName()).get(0).getAge(),则需要执行Stream::reduce以下操作Stream<Age>

// null doesn't occurunless the Age::getAge returns null
// The reducing would be much easier if the age is int
// Feel free to find max/min of the ages... up to you
String age = map.get(e.getName()).stream().map(Age::getAge).reduce(...).orElse(null); 
Run Code Online (Sandbox Code Playgroud)

结论:方法虽然笨拙,但我个人会坚持使用程序性 for 循环方法。