【问题标题】:How to use Java streams to combine child generated lists into a single list?如何使用 Java 流将子生成的列表组合成一个列表?
【发布时间】:2018-07-24 01:32:37
【问题描述】:
在下面的代码中,我不喜欢在流外部定义List<EmailDraft> 列表。我很确定有一种方法可以让流处理直接返回List<EmailDraft> 列表,我只是不知道该怎么做。想法?
List<EmailDraft> drafts /* <-- don't like this */
= new LinkedList<>();
List<SyndFeed> feeds
= evnt.getFeeds();
feeds.stream().forEach(
sf -> sf.getEntries().stream().forEach(se -> {
EmailDraft ed = new EmailDraft();
// Title
ed.setTitle(sf.getTitle());
// ....
// Add to list
drafts.add(ed); /* <-- don't like this either */
})
);
【问题讨论】:
标签:
java
lambda
java-stream
flatmap
【解决方案1】:
您可以在提要上使用flatMap 并在列表中使用collect 所有EmailDrafts,如下所示:
List<EmailDraft> emailDrafts =
feeds.stream()
.flatMap(
sf -> sf.getEntries().stream().map(se -> {
EmailDraft ed = new EmailDraft();
// Title
ed.setTitle(sf.getTitle());
return ed;
})
).collect(Collectors.toList());
【解决方案2】:
使用map
feeds.stream().flatmap(
sf -> sf.getEntries().stream()).map(se -> {
EmailDraft ed = new EmailDraft();
// Title
ed.setTitle(sf.getTitle());
// ....
return ed;
})
);
【解决方案3】:
另一种使用范围创建title 流的替代方法,重复sf.getEntries() 中的元素数量:
List<EmailDraft> drafts = feeds.stream()
.flatMap( sf -> IntStream.range( 0, sf.getEntries().size() ).mapToObj( i -> sf.getTitle() ) )
.map( t -> {
EmailDraft ed = new EmailDraft();
ed.setTitle(t);
return ed;
}
)
.collect( Collectors.toList() );
【解决方案4】:
您可以使用旧的 Java-8 之前的方式来完成,而不是过度复杂化并使用流来完成所有事情:
List<EmailDraft> drafts = new ArrayList<>();
for(SyndFeed sf : feeds){
for(int i = sf.getEntries().size(); i > 0; i--){
EmailDraft ed = new EmailDraft();
ed.setTitle(sf.getTitle());
drafts.add(ed);
}
}
应该首选哪个 IMO,因为它是如此简单的任务。