The*_*ice 5 java java-8 java-stream
我想了解flatMap
使用Collector
s 执行一段时间的方法.这是一个例子.
场景:
我有以下接口:
interface Ic {
//empty
}
interface Ib {
Stream<Ic> getCs();
}
interface Ia {
String getName();
Stream<Ib> getBs();
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试实现以下方法:
Map<String, Long> total_of_C_per_A (Stream<Ia> streamOfA) {
return streamOfA.collect(groupBy(Ia::getName, ???));
}
Run Code Online (Sandbox Code Playgroud)
该分类功能相当straitforward,我的问题是与下游收集器.我需要计算与"A"相关的"C"数.
我试图:
如果我想简单地返回计数而不创建地图,我会这样做:
streamOfA
.flatMap(Ia::getBs)
.flatMap(Ib::getCs)
.count();
Run Code Online (Sandbox Code Playgroud)
但是这个Collectors
类只允许我做映射操作.我还能尝试做些什么?
谢谢.
这个答案指出你已经进入了正确的方向,但是没有必要嵌套多个mapping
收集器,因为你可以将这些函数写入一个lambda表达式.考虑到summingLong
收集器需要一个求值的函数long
,你可以简单地将该函数传递给收集器而不需要任何mapping
收集器:
Map<String, Long> total_of_C_per_A (Stream<Ia> streamOfA) {
return streamOfA.collect(groupingBy(
Ia::getName,
summingLong(ia -> ia.getBs().flatMap(Ib::getCs).count())));
}
Run Code Online (Sandbox Code Playgroud)
这也具有以下优点:long
值不会加到Long
实例框中.
还有另一种选择flatMap
:
Map<String, Long> total_of_C_per_A (Stream<Ia> streamOfA) {
return streamOfA.collect(groupingBy(
Ia::getName,
summingLong(ia -> ia.getBs().mapToLong(ib -> ib.getCs().count()).sum())));
}
Run Code Online (Sandbox Code Playgroud)
文档将收集器#映射描述为:
通过在累积之前将映射函数应用于每个输入元素,使接受类型元素的收集器适应一个接受类型的
U
元素T
.的
mapping()
在使用时,收集器是最有用的多级还原,如一个下游groupingBy
或partitioningBy
.
这意味着你可以尽可能地编写任何可能的Collector
s.
import static java.util.stream.Collectors.*;
Map<String, Long> total_of_C_per_A(Stream<Ia> streamOfA) {
return streamOfA.collect(groupingBy(
Ia::getName,
mapping(
Ia::getBs,
mapping(
it -> it.flatMap(Ib::getCs),
// reduce() does boxing & unboxing ---v
mapping(Stream::count, reducing(0L,Long::sum))
)
)
));
}
Run Code Online (Sandbox Code Playgroud)
或者使用收藏家#summingLong代替.
Map<String, Long> total_of_C_per_A(Stream<Ia> streamOfA) {
return streamOfA.collect(groupingBy(
Ia::getName,
mapping(
Ia::getBs,
mapping(
it -> it.flatMap(Ib::getCs),
// summingLong() does boxing ---v
mapping(Stream::count, summingLong(Long::longValue))
// Long::longValue does unboxing operation ---^
)
)
));
}
Run Code Online (Sandbox Code Playgroud)
感谢@Holger指出上面代码的潜在问题,你可以简单地使用summingLong(Stream::count)
代替.在这种方法是没有必要拳击Stream#count
返回long
一个Long
.并Long::longValue
取消装箱Long
到long
.
Map<String, Long> total_of_C_per_A(Stream<Ia> streamOfA) {
return streamOfA.collect(groupingBy(
Ia::getName,
mapping(
Ia::getBs,
// summingLong() doesn't any boxing ---v
mapping(it -> it.flatMap(Ib::getCs), summingLong(Stream::count))
)
));
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
353 次 |
最近记录: |