Java 8中怎么利用Streams API对Stream进行分组和分区
本篇文章给大家分享的是有关Java 8中怎么利用Streams API对Stream进行分组和分区,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
分组
首先,我们利用(lambda表达式出现之前的)命令式风格Java 程序对流中的雇员按城市进行分组:
Map> result = new HashMap<>();
for (Employee e : employees) {
String city = e.getCity();
List empsInCity = result.get(city);
if (empsInCity == null) {
empsInCity = new ArrayList<>();
result.put(city, empsInCity);
}
empsInCity.add(e);
}
你可能很熟悉写这样的代码,你也看到了,一个如此简单的任务就需要这么多代码!
而在 Java 8 中,你可以使用 groupingBy 收集器,一条语句就能完成相同的功能,像这样:
Map> employeesByCity =
employees.stream().collect(groupingBy(Employee::getCity));
结果如下面的 map 所示:
{New York=[Charles], Hong Kong=[Dorothy], London=[Alice, Bob]}
还可以计算每个城市中雇员的数量,只需传递一个计数收集器给 groupingBy 收集器。第二个收集器的作用是在流分类的同一个组中对每个元素进行递归操作。
Map numEmployeesByCity =
employees.stream().collect(groupingBy(Employee::getCity, counting()));
结果如下面的 map 所示:
{New York=1, Hong Kong=1, London=2}
顺便提一下,该功能与下面的 SQL 语句是等同的:
select city, count(*) from Employee group by city
另一个例子是计算每个城市的平均年龄,这可以联合使用 averagingInt 和 groupingBy 收集器:
Map avgSalesByCity =
employees.stream().collect(groupingBy(Employee::getCity,
averagingInt(Employee::getNumSales)));
结果如下 map 所示:
{New York=160.0, Hong Kong=190.0, London=175.0}
分区
分区是一种特殊的分组,结果 map 至少包含两个不同的分组--一个true,一个false。例如,如果想找出最优秀的员工,你可以将所有雇员分为两组,一组销售量大于 N,另一组小于 N,使用 partitioningBy 收集器:
Map> partitioned =
employees.stream().collect(partitioningBy(e -> e.getNumSales() > 150));
输出如下结果:
{false=[Bob], true=[Alice, Charles, Dorothy]}
你也可以将 groupingBy 收集器传递给 partitioningBy 收集器来将联合使用分区和分组。例如,你可以统计每个分区中的每个城市的雇员人数:
Map> result =
employees.stream().collect(partitioningBy(e -> e.getNumSales() > 150,
groupingBy(Employee::getCity, counting())));
这样会生成一个二级 Map:
{false={London=1}, true={New York=1, Hong Kong=1, London=1}}
以上就是Java 8中怎么利用Streams API对Stream进行分组和分区,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。