![Java核心技术·卷Ⅱ:高级特性(原书第10版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/937/34339937/b_34339937.jpg)
1.11 下游收集器
groupingBy方法会产生一个映射表,它的每个值都是一个列表。如果想要以某种方式来处理这些列表,就需要提供一个“下游收集器”。例如,如果想要获得集而不是列表,那么可以使用上一节中看到的Collector.toSet收集器:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/024-i.jpg?sign=1738824807-4mTa5gEfEoVe16aSwRbMa131fXu5uZeo-0-4909480304ce033e021a69970a5fd877)
注意:在本节的这个示例以及后续示例中,我们认为静态导入java.util.stream.Collectors.*会使表达式更容易阅读。
Java提供了多种可以将群组元素约简为数字的收集器:
·counting会产生收集到的元素的个数。例如:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/024-2-i.jpg?sign=1738824807-sEr7Hx1LbDMLUYQ2CQ3C3OoGveqCWvjt-0-8868e8667531b2353c334f8d9abd49cb)
可以对每个国家有多少个Locale进行计数。
·summing(Int|Long|Double)会接受一个函数作为引元,将该函数应用到下游元素中,并产生它们的和。例如:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/024-3-i.jpg?sign=1738824807-03Urh50I6VA4OrgNc2EILpvNwU2i3kEp-0-3d67570a862c77eb92f1883317efaa3c)
可以计算城市流中每个州的人口总和。
·maxBy和minBy会接受一个比较器,并产生下游元素中的最大值和最小值。例如:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/024-4-i.jpg?sign=1738824807-CndmzXdBTxDrrWTol0XPiXepXMG3riVx-0-82488cd10f3e85fd2c3a540c6d97d66e)
可以产生每个州中最大的城市。
mapping方法会产生将函数应用到下游结果上的收集器,并将函数值传递给另一个收集器。例如:
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/025-i.jpg?sign=1738824807-6rfS5nWSQKo96hhog0oZvz17QWe0BRJ5-0-79428133433976ffdde7affdb4a5205e)
这里,我们按照州将城市群组在一起。在每个州内部,我们生成了各个城市的名字,并按照最大长度约简。
mapping方法还针对上一节中的问题,即把某国所有的语言收集到一个集中,产生了一种更佳的解决方案。
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/025-2-i.jpg?sign=1738824807-oc5BW3eV0XUUT1Zmc8DUTnbcHSH1usbw-0-82e91d22399efa6867c0d9e80e9733b1)
在上一节中,我们使用的是toMap而不是groupingBy。而在上述这种方式中,我们无须操心如何将各个集组合起来。
如果群组和映射函数的返回值为int、long或double,那么可以将元素收集到汇总统计对象中,就像1.8节中所讨论的一样。例如,
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/025-3-i.jpg?sign=1738824807-745dP5uA0EzpD352KuNVDl78F1EPFw68-0-f952669efe74d30dc0f4f735d907b031)
然后,可以从每个组的汇总统计对象中获取这些函数值的总和、个数、平均值、最小值和最大值。
注意:还有3个版本的reducing方法,它们都应用了通用的约简操作,正如1.12节中所描述的一样。
将收集器组合起来是一种很强大的方式,但是它也可能会导致产生非常复杂的表达式。它们的最佳用法是与groupingBy和partitioningBy一起处理“下游的”映射表中的值。否则,应该直接在流上应用诸如map、reduce、count、max或min这样的方法。
程序清单1-6中的示例程序演示了下游收集器。
程序清单1-6 collecting/DownstreamCollectors.java
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/025-4-i.jpg?sign=1738824807-izYk3rkGrwEhhrlenOT0Cp8i6cMy3wLS-0-b6b9ff5126035ad5a9ef79afbdb85615)
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/026-i.jpg?sign=1738824807-7Gb0MoW82ETrhTKtfuA63enDklfaX0Er-0-8bdc191aa895ebc28b08388c570676b2)
![](https://epubservercos.yuewen.com/F21227/18365861501241106/epubprivate/OEBPS/Images/027-i.jpg?sign=1738824807-A27cUxKcl8D8i93GKFSl8LpASBRfgDE0-0-cef86a46fe92548b459e4f2bc1f00631)
java.util.stream.Collectors 8
·static<T>Collector<T,?,Long>counting()
产生一个可以对收集到的元素进行计数的收集器。
·static<T>Collector<T,?,Integer>summingInt(ToIntFunction<?super T>mapper)
·static<T>Collector<T,?,Long>summingLong(ToLongFunction<?super T>mapper)
·static<T>Collector<T,?,Double>summingDouble(ToDoubleFunction<?super T>mapper)
产生一个收集器,对将mapper应用到收集到的元素上之后产生的值计算总和。
·static<T>Collector<T,?,Optional<T>>maxBy(Comparator<?super T>comparator)
·static<T>Collector<T,?,Optional<T>>minBy(Comparator<?super T>comparator)
产生一个收集器,使用comparator指定的排序方法,计算收集到的元素中的最大值和最小值。
·static<T,U,A,R>Collector<T,?,R>mapping(Function<?super T,?extends U>mapper,Collector<?super U,A,R>downstream)
产生一个收集器,它会产生一个映射表,其键是将mapper应用到收集到的数据上而产生的,其值是使用downstream收集器收集到的具有相同键的元素。