从列表列表以功能性方式创建列表的最简洁方法?

时间:2020-08-27 16:37:55

标签: java functional-programming java-stream

我有以下代码:

List<DataObject> dataObjectList = new ArrayList<>();
for (Company company : companyRepository.findAll()) {
    for (Employee employee : company.employees) {
        DataOjbect dataObject = new dataObject();
        dataObject.setCompanyName(company.getName());
        dataObject.setEmployeeName(employee.getName());
        dataObjectList.add(dataObject);
    }
}

在Java中以功能样式编写此代码的最干净的方法是什么?

请注意,companyRepository.findAll()返回一个Iterator,因此您不能简单地从其中创建一个流。

2 个答案:

答案 0 :(得分:2)

要从Stream创建Iterator,您需要先创建Iterable,然后使用Spliterator方法将其Iterable::spliterator传递到StreamSupport::stream

Stream<?> stream = StreamSupport.stream(iterable.spliterator(), false);

只要Iterable仅具有一个抽象方法,就可以从Iterator通过lambda表达式创建Iterable,因此该接口符合该表达式的要求。

Iterable<Company> iterable = () -> companyRepository.findAll();
Stream<Company> stream = StreamSupport.stream(iterable.spliterator(), false);

现在,事情变得简单了:利用flatMap的优势来简化嵌套列表结构(每个公司都有员工列表的公司列表。您需要正确创建每个DataObject只要其实例化依赖于flatMap参数,就可以在company.getName()方法中使用

List<DataObject> dataObjectList = StreamSupport.stream(iterable.spliterator(), false)
        .flatMap(company -> company.getEmployees().stream()
                .map(employee -> {
                    DataObject dataObject = new DataObject();
                    dataObject.setCompanyName(company.getName());
                    dataObject.setEmployeeName(employee.getName());
                    return dataObject;
                }))
        .collect(Collectors.toList());

...,如果使用构造函数,则不那么冗长...

List<DataObject> dataObjectList = StreamSupport.stream(iterable.spliterator(), false)
        .flatMap(company -> company.getEmployees().stream()
            .map(employee -> new DataObject(company.getName(), employee.getName())))
        .collect(Collectors.toList());

答案 1 :(得分:1)

Imo,使用流执行此操作并没有真正的好处。我会坚持你所拥有的。通过在您的constructor类中创建一个DataObject,可以使其更加简洁。然后您可以执行以下操作:

List<DataObject> dataObjectList = new ArrayList<>();

for (Company company : companyRepository.findAll()) {
    for (Employee employee : company.employees) {
        dataObjectList.add(new DataObject(company.getName(), employee.getName()));
    }
}