英文:
The cleanest way to create a list in a functional way from a list of lists?
问题
List<DataObject> dataObjectList = companyRepository.findAll().stream()
.flatMap(company -> company.getEmployees().stream()
.map(employee -> {
DataObject dataObject = new DataObject();
dataObject.setCompanyName(company.getName());
dataObject.setEmployeeName(employee.getName());
return dataObject;
}))
.collect(Collectors.toList());
英文:
I have the following code:
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);
}
}
What is the cleanest way to write this code in a functional style in java?
Note that companyRepository.findAll()
returns an Iterator, so you can't simply create a stream out of it.
答案1
得分: 2
创建一个 Stream
从 Iterator
,你需要首先创建一个 Iterable
,然后使用 Iterable::spliterator
方法传递其 Spliterator
到 StreamSupport::stream
。
Stream<?> stream = StreamSupport.stream(iterable.spliterator(), false);
Iterable
可以通过 lambda 表达式从 Iterator
创建,只要 Iterable
只有一个抽象方法,因此该接口适合这样的表达式。
Iterable<Company> iterable = () -> companyRepository.findAll();
Stream<Company> stream = StreamSupport.stream(iterable.spliterator(), false);
现在,事情变得简单:利用 flatMap
的优势来展平嵌套的列表结构(一个公司列表,每个公司都有一个员工列表)。你需要在 flatMap
方法内部创建每个 DataObject
,只要它的实例化依赖于 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());
英文:
To create a Stream
from Iterator
, you need to create Iterable
first and then pass its Spliterator
using Iterable::spliterator
method into StreamSupport::stream
.
Stream<?> stream = StreamSupport.stream(iterable.spliterator(), false);
The Iterable
can be created from Iterator
through a lambda expression as long as Iterable
has only one abstract method, therefore the interface is qualified for such expression.
Iterable<Company> iterable = () -> companyRepository.findAll();
Stream<Company> stream = StreamSupport.stream(iterable.spliterator(), false);
Now, the things get easy: Use the advantage of flatMap
to flatten the nested list structure (a list of companies where each company has a list of employees. You need to create each DataObject
right inside the flatMap
method as long as its instantiation relies on the company.getName()
parameter:
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());
... and less verbose if you use a constructor ...
List<DataObject> dataObjectList = StreamSupport.stream(iterable.spliterator(), false)
.flatMap(company -> company.getEmployees().stream()
.map(employee -> new DataObject(company.getName(), employee.getName())))
.collect(Collectors.toList());
答案2
得分: 1
在我看来,使用流来完成这个任务实际上没有真正的好处。我建议你继续使用你目前的方法。你可以通过在你的DataObject
类中创建一个constructor
来使代码更加简洁。然后你可以这样做:
List<DataObject> dataObjectList = new ArrayList<>();
for (Company company : companyRepository.findAll()) {
for (Employee employee : company.employees) {
dataObjectList.add(new DataObject(company.getName(), employee.getName()));
}
}
英文:
Imo, there is no real benefit to using streams to do this. I would stick with what you have. You could make it more concise by creating a constructor
in your DataObject
class. Then you could do the following:
List<DataObject> dataObjectList = new ArrayList<>();
for (Company company : companyRepository.findAll()) {
for (Employee employee : company.employees) {
dataObjectList.add(new DataObject(company.getName(), employee.getName()));
}
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论