如何使用Java 8的流(Stream)来替换嵌套的for循环?

25

在学习Java 8的流和Lambda表达式时,我尝试使用流来替换以下嵌套的for循环:

List<Long> deskIds = new ArrayList<>();
for(ProvidedService memberService : service.getAllNodesDepthFirst()){
   for(Desk d : memberService.getDesks()){
     deskIds.add(d.getId());
   }
}

该循环遍历“ProvidedService”对象的列表,对于每个对象,会遍历“Desk”对象的一个列表属性,并将“Id”字段提取到列表中。

我使用流编写了以下代码:

List<Long> deskIds = new ArrayList<>();
service.getAllNodesDepthFirst().stream().forEach(srv -> {
    deskIds.addAll(srv.getDesks().stream().map(Desk::getId).collect(Collectors.toList()));
});

这是正确/最佳的方法吗?还是有一种方法可以在不使用第二个嵌套流的情况下完成此操作?


我认为这很好。你的方法没有问题。 - Prakhar Asthana
更多内容请查看此链接:http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html - Prakhar Asthana
@Prakhar:是的,我的方法可行,但有点幼稚,我认为应该有一些方法可以像assylias演示的那样简化它。 - Pierre Henry
1个回答

33

我可能会这样写:

List<Long> deskIds = service.getAllNodesDepthFirst().stream()
                                          .flatMap(p -> p.getDesks().stream())
                                          .map(Desk::getId)
                                          .collect(toList());

1
是的,我希望有类似“flatMap”的东西! - Pierre Henry
@assylias 如果我想要得到一个映射而不是列表,有没有简单的方法,其中映射是提供服务的某个ID,值是桌子ID。 - Naman
@assylias 我看了一下 groupingBy,但似乎我只能得到 Map<String, List<String>>,而我不想要那个,我希望得到 Map<String, String>。你能建议一下我该怎么做吗? - Naman
针对您具体的情况,提出单独的问题会更合适。 - assylias

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接