java 8流从类型A的集合创建类型B的集合

java 8流从类型A的集合创建类型B的集合,java,collections,java-8,java-stream,Java,Collections,Java 8,Java Stream,我想使用流从类型B创建类型a的集合 假设我有两门课 Class Employee{ String firstName; String lastName; int age; String id; String email; double salary; } Class Person { String firstName; String lastName; String email; } 为了从员工集合中创建人员集合,我编写了以下代码 public

我想使用流从类型B创建类型a的集合

假设我有两门课

Class Employee{
   String firstName;
   String lastName;
   int age;
   String id;
   String email;
   double salary;
}

Class Person {
  String firstName;
  String lastName;
  String email;
}
为了从员工集合中创建人员集合,我编写了以下代码

public static List<Person> createPersonsFromEmployees(List<Employee> employees) {

        List<Person> persons = new ArrayList<>();

        employees.stream().filter(Object :: nonNull)
                  .forEach(e -> {
                       persons.add(new Person(e.getFirstName(),
                                           e.getLastName(), 
                                           e.getEmail());
                   };)


        return persons;
}
公共静态列表createPersonsFromEmployees(列出员工){
List persons=new ArrayList();
employees.stream().filter(对象::非空)
.forEach(e->{
persons.add(新的persone(例如getFirstName()),
e、 getLastName(),
e、 getEmail());
};)
返回人员;
}
目前,这段代码有效。但我想知道是否有更好的方法从
Employee
创建
Person
集合,而无需使用
forEach
创建适配器类:

class EmployeeToPersonAdapter {

    private EmployeeToPersonAdapter() {
    }

    public static Person toPerson(Employee employee) {
        if (employee == null) {
            return null;
        }
        return new Person(employee.getFirstName(),
                employee.getLastName(),
                employee.getEmail());
    }
}
然后使用它:

public static List<Person> createPersonsFromEmployees(List<Employee> employees) {
    return employees.stream()
            .filter(Objects::nonNull)
            .map(EmployeeToPersonAdapter::toPerson)
            .collect(Collectors.toList());
}
公共静态列表createPersonsFromEmployees(列出员工){
return employees.stream()
.filter(对象::非空)
.map(EmployeeToPersonAdapter::toPerson)
.collect(Collectors.toList());
}

这里有一个更简洁的方法。在流中使用.forEach()表明可能有更好的方法使用流。流是功能性的,它们试图远离易变性

public static List<Person> createPersonsFromEmployees(List<Employee> employees)
    Function<Employee, Person> employeeToPerson = e -> new Person(e.getFirstName, e.getLaseName(), e.getEmail());

    return employees.stream()
                    .filter(Object :: nonNull)
                    .map(employeeToPerson)
                    .collect(Collectors.toList());

}
公共静态列表createPersonsFromEmployees(列出员工)
函数employeeToPerson=e->newperson(e.getFirstName,e.getLaseName(),e.getEmail());
return employees.stream()
.filter(对象::非空)
.map(员工个人)
.collect(Collectors.toList());
}

员工
映射到您可以使用的
人员
,其他人已经提供了,因此我将跳过它

注意,映射方式比映射方式快,因为
collect(mapping(…)
是O(N),但是
map(…)。collect(…)
是O(2N),但是
map(…)。collect(…)
collect(mapping(…)
更可读,并且
mapping
引用公共
转换(员工)
method reference而不是
Function
,后者将被重用为将
员工
转换为
的方法。然后两个
转换
方法具有相同的语义,它们都是方法

公共列表转换(列表员工)抛出可丢弃{
return employees.stream()
.filter(对象::非空)
.collect(Collectors.mapping(this::transform,Collectors.toList());
}
公众人物转换(员工it){
返回新人(it.firstName、it.lastName、it.email);
}

我同意此解决方案。我唯一要做的更改是为Person类创建一个生成器,以便以更智能的方式处理构造函数中的字段。非常感谢您分享您的想法和投入,以及如何使其更好。感谢您的大量解释。感谢您抽出时间并分享解决方案。
public List<Person> transform(List<Employee> employees) throws Throwable {
    return employees.stream()
            .filter(Objects::nonNull)
            .collect(Collectors.mapping(this::transform, Collectors.toList()));
}

public Person transform(Employee it) {
    return new Person(it.firstName, it.lastName, it.email);
}