Java8提供了强大的Stream API,对于操作集合、数组等,非常方便也非常优雅。本文主要整理下平时常用的一些操作。
1. List
List操作是Stream中最常见的操作,下面将介绍一些常用的List操作。
1.1. 去重
1 | public class StreamTest { |
上述测试代码输出如下:
1 | oldList: [a, b, a, c] |
去重的核心代码:
1 | oldList.stream().distinct().collect(Collectors.toList()) |
1.2. 数组转List
1 | // int数组转List |
1.3. List转数组
1 | String[] ss = listStrings.stream().toArray(String[]::new); |
1.4. List转Map
1.4.1. 方法引用
常见的List转Map,用的是方法引用,分别生成key、value
数据集见下节
1 | Map<String, Person> cityMap = persons.stream() |
以上输出:
1 | city map: { |
1.4.2. lambda
有时候,list转map,没办法直接用方法引用,也可以用lambda
1 | .collect(Collectors.toMap( |
2. 分组
假设我们有如下数据:
姓名 | 职业 | 城市 |
---|---|---|
wxweven | 程序员 | huangshi |
even | 教师 | beijing |
meixiaoxi | 足球员 | basailuona |
meidaxi | 教师 | beijing |
每条记录对应的POJO如下:
1 | public class Person { |
2.1. 分组聚合
如果想按照城市分组,即转化为一个map:
key为city,value为该city对应的Person对象集合
代码如下:
1 |
|
上述代码输出:
1 | 按城市分组后:{ |
可以看到,city为beijing
的两个person被分配到了同一组,类似于MySQL中的groupBy的效果(不过MySQL中的groupBy只能保留一条数据)。
2.2. 分组后聚合计算
还是以上面的数据来举栗子,比如说要计算每个城市的人数,只需传递一个计数收集器给 groupingBy 收集器。第二个收集器的作用是在流分类的同一个组中对每个元素进行递归操作。代码如下:
1 | Map<String, Long> nums = persons.stream() |
输出如下:
1 | 每个城市的人数:{basailuona=1, beijing=2, huangshi=1} |
这个其实和MySQL中的语句是一样的功能:
1 | select city, count(*) from Person group by city |
除了counting
之外,Stream也支持其他类型的聚合函数,如averagingInt
(求平均值)、summingInt
(求和)、maxBy
(最大值)、minBy
(最小值)等MySQL中支持的聚合函数。
2.3. 分组后汇总
我们来看Stack Overflow上的一个问题:
If the input was
[(1, “one”), (1, “eins”), (1, “uno”), (2, “two”), (3, “three”)]
the output would be
{ 1 = [“one”, “eins”, “uno”], 2 = [“two”], 3 = [“three”] }
1 | tuples.stream() |
3. Map转化
1 | Map<Integer, List> maps = getMap(); |
4. flatMap
flatMap用户将几个小的list合并到一个大的list,即『打平』的意思,看下面的图:
假设我们有两个List:
1 | List<Integer> list1 = Arrays.asList(1, 2, 3); |
如果我们想把list1和list2合并成一个List,新的List值为:[1, 2, 3, 4, 5, 6]
, 那么可以用 flatMap
来实现。完整例子如下:
1 |
|
输出如下:
1 | newList=[1, 2, 3, 4, 5, 6, 7, 8, 9] |