Java 如何避免嵌套的Collection.stream()调用?

Java 如何避免嵌套的Collection.stream()调用?,java,lambda,java-8,Java,Lambda,Java 8,假设我们有以下Map Map<String, List<String>> peopleByCity = new TreeMap<>(); 借助Stream API的工具,对于每对类型[City;Person],我想应用一些操作,比如打印: London : Steve London : John Paris : Thierry Sofia : Peter Sofia : Konstantin Sofia : Ivan 一个可能的(但不是

假设我们有以下
Map

Map<String, List<String>> peopleByCity = new TreeMap<>();
借助Stream API的工具,对于每对类型
[City;Person]
,我想应用一些操作,比如打印:

 London : Steve
 London : John
 Paris  : Thierry
 Sofia  : Peter
 Sofia  : Konstantin
 Sofia  : Ivan
一个可能的(但不是很好的)解决方案是:

peopleByCity.entrySet()
            .stream()
            .forEach( entry -> {
                 String city = entry.getKey();
                 entry.getValue().
                      .stream()   <-- the nested Collection.stream() call
                      .forEach(
                         person -> System.out.println(city + ";" + person));
            });
peopleByCity.entrySet()
.stream()
.forEach(条目->{
字符串city=entry.getKey();
entry.getValue()。
.stream()System.out.println(city+“;”+person));
});
我们如何通过创建对其他流/收集器功能的调用链来避免对的嵌套调用?

一种方法是“平面映射”列表:

peopleByCity.entrySet().stream()
        .flatMap(e -> e.getValue().stream().map(p -> e.getKey() + ";" + p))
        .forEach(System.out::println);
另一种方法是使用两个
forEach

peopleByCity.forEach((city, people) -> 
        people.forEach(person -> System.out.println(city + ";" + person)));
但最后,我不认为有一种简单的方法可以流式处理列表,除非您编写一个自定义收集器(但嵌套流将在收集器中)。

一种方法是“平面映射”列表:

peopleByCity.entrySet().stream()
        .flatMap(e -> e.getValue().stream().map(p -> e.getKey() + ";" + p))
        .forEach(System.out::println);
另一种方法是使用两个
forEach

peopleByCity.forEach((city, people) -> 
        people.forEach(person -> System.out.println(city + ";" + person)));

但是最后,我不认为有一种简单的方法可以流式处理列表,除非您编写一个自定义收集器(但是嵌套流将在收集器中)。

可以工作,但仍然有一个嵌套的
.stream()
flatMap
函数体中调用。@kocko我可以提出第二个选项,就像第二个更好,尽管我开始认为没有办法避免调用lambdas中的高阶函数(这是问题的一般要点)。对于
flatMap()
,您有我的+1,这有点错误,因为您是flatMapping
Map。Entry
对象,而不是
List
s:)无论是
flatMap
还是嵌套的
stream()
调用都没有问题。如果考虑性能,使用
flatMap
方法和
collect
在打印前将
String
s压缩到单个
StringBuffer
中是中等大小流的最佳选择。工作正常,但仍有嵌套的
.stream()
flatMap
函数体中调用。@kocko我可以提出第二个选项,就像第二个更好,尽管我开始认为没有办法避免调用lambdas中的高阶函数(这是问题的一般要点)。对于
flatMap()
,您有我的+1,这有点错误,因为您是flatMapping
Map。Entry
对象,而不是
List
s:)无论是
flatMap
还是嵌套的
stream()
调用都没有问题。如果考虑性能,使用
flatMap
方法和
collect
在打印前将
String
s放入单个
StringBuffer
是中等大小流的最佳选择。更好的问题是,为什么您认为嵌套流调用应该避免?@BrianGoetz,我正在重构一个带有两个嵌套for循环的代码段,我想知道是否有一种方法可以创建一系列高阶函数调用,其工作方式与MongoDB运算符类似。更好的问题是,为什么您认为嵌套流调用是需要避免的?@BrianGoetz,我正在重构一个带有两个嵌套for循环的代码段,我想知道是否有一种方法可以创建一系列高阶函数调用,它们的工作方式与MongoDB的操作符类似。