【问题标题】:java 8 stream creating collection of type B from collection of type A [duplicate]java 8流从A类型的集合创建B类型的集合[重复]
【发布时间】:2017-04-10 04:47:12
【问题描述】:

我想使用流从类型 B 创建一个类型 A 的集合。

假设我有两个班级

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

Class Person {
  String firstName;
  String lastName;
  String email;
}

为了从 Employee 集合创建 Person 集合,我编写了以下代码

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;
}

目前,这段代码有效。但我想知道是否有更好的方法可以在不使用forEach 的情况下从Employee 创建Person 的集合。

【问题讨论】:

    标签: java collections java-8 java-stream


    【解决方案1】:

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

    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());
    
    }
    

    【讨论】:

    • 我同意这个解决方案。我唯一要改变的是为 Person 类创建一个 Builder 来以更智能的方式处理构造函数中的字段。
    • 非常感谢您分享您的想法和意见,以及如何使其变得更好。
    【解决方案2】:

    创建适配器类:

    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());
    }
    

    【讨论】:

    • 感谢您抽出时间并分享解决方案。
    【解决方案3】:

    Employee 映射到Person 您可以使用其他人已经提供的Collectors.mapping/Stream.map,所以我将跳过它。

    注意,映射方式比 map 方式快,然后 collect 方式,因为 collect(mapping(...)) 是 O(N) 但 map(...).collect(...) 是 O(2N),但 map(...).collect(...)collect(mapping(...)) 更具可读性,mapping 参考到公共的transform(Employee) 方法引用而不是Function&lt;Employee,Person&gt;,它将被重用作为将Employee 转换为Person 的方法。然后两个transform方法语义相同,都是adapter方法。

    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);
    }
    

    【讨论】:

    • 感谢您的大量解释。
    猜你喜欢
    • 1970-01-01
    • 2011-04-16
    • 2011-09-24
    • 1970-01-01
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-28
    相关资源
    最近更新 更多