需求:过滤分组一所中学里身高在 160cm 以上的男女同学

之前的代码实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
Map<String, List<Student>> stuMap = new HashMap<String, List<Student>>();
for (Student stu: studentsList) {
if (stu.getHeight() > 160) { //如果身高大于160
if (stuMap.get(stu.getSex()) == null) { //该性别还没分类
List<Student> list = new ArrayList<Student>(); //新建该性别学生的
list.add(stu);//将学生放进去列表
stuMap.put(stu.getSex(), list);//将列表放到map中
} else { //该性别分类已存在
stuMap.get(stu.getSex()).add(stu);//该性别分类已存在,则直接放进去
}
}
}

使用Stream API实现:

串行实现:

1
Map<String, List<Student>> stuMap = stuList.stream().filter((Student s) -> s.getHeight() > 160) .collect(Collectors.groupingBy(Student ::getSex)); 

并行实现:

1
Map<String, List<Student>> stuMap = stuList.parallelStream().filter((Student s) -> s.getHeight() > 160) .collect(Collectors.groupingBy(Student ::getSex)); 

Stream 如何优化遍历

官方将 Stream 中的操作分为两大类:中间操作(Intermediate operations)和终结操作(Terminal operations)

中间操作只对操作进行了记录,即只会返回一个流,不会进行计算操作,而终结操作是实现了计算操作。

中间操作又可以分为无状态(Stateless)与有状态(Stateful)操作,前者是指元素的处理不受之前元素的影响,后者是指该操作只有拿到所有元素之后才能继续下去。

终结操作又可以分为短路(Short-circuiting)与非短路(Unshort-circuiting)操作,前者是指遇到某些符合条件的元素就可以得到最终结果,后者是指必须处理完所有元素才能得到最终结果。

image-20230524223653374

Stream如何迭代大数据集合:

1
2
3
4
5
6
7
8

List<String> names = Arrays.asList("张三", "李四", "王老五", "李三", "刘老四", "王小二", "张四", "张五六七");

String maxLenStartWithZ = names.stream()
.filter(name -> name.startsWith("张"))
.mapToInt(String::length)
.max()
.toString();

Stream 并行处理

1
2
3
4
5
6
7
8
List<String> names = Arrays.asList("张三", "李四", "王老五", "李三", "刘老四", "王小二", "张四", "张五六七");

String maxLenStartWithZ = names.stream()
.parallel()
.filter(name -> name.startsWith("张"))
.mapToInt(String::length)
.max()
.toString();

参考

《Java性能调优实战》