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