JAVA 8 Stream API 对Stream进行分组、分区
来源:互联网 发布:计算工程量的软件 编辑:程序博客网 时间:2024/06/06 19:52
这篇文章展示了如何使用 Streams API 中的 Collector 及 groupingBy 和 partitioningBy 来对流中的元素进行分组和分区。
思考一下 Employee 对象流,每个对象对应一个名字、城市和销售数量,如下表所示:
+----------+------------+-----------------+| Name | City | Number of Sales |+----------+------------+-----------------+| Alice | London | 200 || Bob | London | 150 || Charles | New York | 160 || Dorothy | Hong Kong | 190 |+----------+------------+-----------------+
分组
首先,我们利用(lambda表达式出现之前的)命令式风格Java 程序对流中的雇员按城市进行分组:
1
2
3
4
5
6
7
8
9
10
Map<String, List<Employee>> result =
new
HashMap<>();
for
(Employee e : employees) {
String city = e.getCity();
List<Employee> empsInCity = result.get(city);
if
(empsInCity ==
null
) {
empsInCity =
new
ArrayList<>();
result.put(city, empsInCity);
}
empsInCity.add(e);
}
你可能很熟悉写这样的代码,你也看到了,一个如此简单的任务就需要这么多代码!
而在 Java 8 中,你可以使用 groupingBy 收集器,一条语句就能完成相同的功能,像这样:
1
2
Map<String, List<Employee>> employeesByCity =
employees.stream().collect(groupingBy(Employee::getCity));
结果如下面的 map 所示:
1
{New York=[Charles], Hong Kong=[Dorothy], London=[Alice, Bob]}
还可以计算每个城市中雇员的数量,只需传递一个计数收集器给 groupingBy 收集器。第二个收集器的作用是在流分类的同一个组中对每个元素进行递归操作。
1
2
Map<String, Long> numEmployeesByCity =
employees.stream().collect(groupingBy(Employee::getCity, counting()));
结果如下面的 map 所示:
1
{New York=
1
, Hong Kong=
1
, London=
2
}
顺便提一下,该功能与下面的 SQL 语句是等同的:
1
select city, count(*) from Employee group by city
另一个例子是计算每个城市的平均年龄,这可以联合使用 averagingInt 和 groupingBy 收集器:
1
2
3
Map<String, Double> avgSalesByCity =
employees.stream().collect(groupingBy(Employee::getCity,
averagingInt(Employee::getNumSales)));
结果如下 map 所示:
1
{New York=
160.0
, Hong Kong=
190.0
, London=
175.0
}
分区
分区是一种特殊的分组,结果 map 至少包含两个不同的分组——一个true,一个false。例如,如果想找出最优秀的员工,你可以将所有雇员分为两组,一组销售量大于 N,另一组小于 N,使用 partitioningBy 收集器:
1
2
Map<Boolean, List<Employee>> partitioned =
employees.stream().collect(partitioningBy(e -> e.getNumSales() >
150
));
输出如下结果:
1
{
false
=[Bob],
true
=[Alice, Charles, Dorothy]}
你也可以将 groupingBy 收集器传递给 partitioningBy 收集器来将联合使用分区和分组。例如,你可以统计每个分区中的每个城市的雇员人数:
1
2
3
Map<Boolean, Map<String, Long>> result =
employees.stream().collect(partitioningBy(e -> e.getNumSales() >
150
,
groupingBy(Employee::getCity, counting())));
这样会生成一个二级 Map:
1
{
false
={London=
1
},
true
={New York=
1
, Hong Kong=
1
, London=
1
}}
译文链接: http://www.importnew.com/17313.html
阅读全文
0 0
- JAVA 8 Stream API 对Stream进行分组、分区
- Java 8 Stream API
- Java 8 Stream API
- Java 8 stream 分组 合并
- Java8 Stream的分组,分区
- Java8 集合元素使用Stream Api进行分组
- Java 8 Stream API详解
- java stream api介绍
- java stream api
- Java 8新特性:Stream API
- Java 8新特性:Stream API
- Java 8新特性 Stream API 编程
- Java 8——Stream API
- Java 8学习之Stream API
- Java 8: Stream API 快速入门
- Java 8 – Stream API 快速入门
- Java 8 Stream API 实用指南
- Stream API:创建Stream
- AWR_最详细解析
- [Shiro入门] (二)缓存管理器SimpleByteSource序列化问题
- oracle vm上安装oracle11g r2 rac(11.2.0.4)
- 层次聚类算法的原理及实现Hierarchical Clustering
- xampp中修改mysql默认空密码(root密码)的方法
- JAVA 8 Stream API 对Stream进行分组、分区
- Request和Urllib2使用代理ip的区别
- 在centos安装mxnet,并配置GPU
- 剑指offer---调整数组顺序使奇数位于偶数前面
- 样式属性声明顺序
- 关于ssi-uploader在strutsMVC的单文件/多文件上传实现
- java 反射详解通俗易懂
- go net/http Client使用——长连接客户端的使用
- 例析Alpha-Beta剪枝