⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 bugpool.blog.csdn.net/article/details/105122681 「bugpool」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

简介

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

熟悉Linux的同学对这种风格一定不陌生,因为它跟Linux的|管道符的思想如出一辙。上面这段话引用自runoob.com,但是其教学代码都是基于String列表进行演示,考虑到实际情况百分之80的时候都是对PO、VO进行处理,因此以下通过一个PO进行讲解。

对比起for循环操作list,最大的弊端就是代码太长太乱了,如果涉及3-4张表的操作,也就是涉及多个PO操作,那个括号简直就是俄罗斯套娃,写到最后真的自己都不知道在写什么

+--------------------+       +------+   +------+   +---+   +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+ +------+ +------+ +---+ +-------+

PO代码

public class UserPo {
private String name;
private Double score;

// 省略构造函数及getter、setter
}

以下操作均以UserPo进行讲解

filter

filter:过滤,就是过滤器,符合条件的通过,不符合条件的过滤掉

// 筛选出成绩不为空的学生人数
count = list.stream().filter(p -> null != p.getScore()).count();

map

map:映射,他将原集合映射成为新的集合,在VO、PO处理的过程中较常见。在本例子中,原集合就是PO集合,新集合可以自定义映射为成绩集合,同时也可以对新集合进行相关操作

// 取出所有学生的成绩
List<Double> scoreList = list.stream().map(p -> p.getScore()).collect(Collectors.toList());

// 将学生姓名集合串成字符串,用逗号分隔
String nameString = list.stream().map(p -> p.getName()).collect(Collectors.joining(","));

sorted

sorted:排序,可以根据指定的字段进行排序

// 按学生成绩逆序排序 正序则不需要加.reversed()
filterList = list.stream().filter(p -> null != p.getScore()).sorted(Comparator.comparing(UserPo::getScore).reversed()).collect(Collectors.toList());

forEach

forEach:这个应该是最常用的,也就是为每一个元素进行自定义操作

除了forEach操作会改变原集合的数据,其他的操作均不会改变原集合,这点务必引起注意

// 学生成绩太差了,及格率太低,给每个学生加10分,放个水
// forEach
filterList.stream().forEach(p -> p.setScore(p.getScore() + 10));

collect

collect:聚合,可以用于GroudBy按指定字段分类,也可以用于返回列表或者拼凑字符串

// 按成绩进行归集
Map<Double, List<UserPo>> groupByScoreMap = list.stream().filter(p -> null != p.getScore()).collect(Collectors.groupingBy(UserPo::getScore));
for (Map.Entry<Double, List<UserPo>> entry : groupByScoreMap.entrySet()) {
System.out.println("成绩:" + entry.getKey() + " 人数:" + entry.getValue().size());
}

// 返回list
List<Double> scoreList = list.stream().map(p -> p.getScore()).collect(Collectors.toList());
// 返回string用逗号分隔
String nameString = list.stream().map(p -> p.getName()).collect(Collectors.joining(","));

statistics

statistics:统计,可以统计中位数,平均值,最大最小值

DoubleSummaryStatistics statistics = filterList.stream().mapToDouble(p -> p.getScore()).summaryStatistics();
System.out.println("列表中最大的数 : " + statistics.getMax());
System.out.println("列表中最小的数 : " + statistics.getMin());
System.out.println("所有数之和 : " + statistics.getSum());
System.out.println("平均数 : " + statistics.getAverage());

parallelStream

parallelStream:并行流,可以利用多线程进行流的操作,提升效率。但是其不具备线程传播性,因此使用时需要充分评估是否需要用并行流操作

// 并行流
count = list.parallelStream().filter(p -> null != p.getScore()).count();

完整代码

package com.cmx.tcn.stream;

/**
* @author: Cai MinXing
**/
public class UserPo {
private String name;
private Double score;

public UserPo(String name, Double score) {
this.name = name;
this.score = score;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Double getScore() {
return score;
}

public void setScore(Double score) {
this.score = score;
}

@Override
public String toString() {
return "UserPo{" +
"name='" + name + '\'' +
", score=" + score +
'}';
}
}
package com.cmx.tcn.stream;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.DoubleSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author: Cai MinXing
* @create: 2020-03-25 18:15
**/
public class StreamTest {

// +--------------------+ +------+ +------+ +---+ +-------+
// | stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
// +--------------------+ +------+ +------+ +---+ +-------+

public static void main(String args[]){

List<UserPo> list = new ArrayList<>();
list.add(new UserPo("小一", 10.d));
list.add(new UserPo("小五", 50.d));
list.add(new UserPo("小六", 60.d));
list.add(new UserPo("小6", 60.d));
list.add(new UserPo("小空", null));
list.add(new UserPo("小九", 90.d));

long count = 0;
List<UserPo> filterList = null;

// filter 过滤器的使用
// 筛选出成绩不为空的学生人数
count = list.stream().filter(p -> null != p.getScore()).count();
System.out.println("参加考试的学生人数:" + count);

// collect
// 筛选出成绩不为空的学生集合
filterList = list.stream().filter(p -> null != p.getScore()).collect(Collectors.toList());
System.out.println("参加考试的学生信息:");
filterList.stream().forEach(System.out::println);

// map 将集合映射为另外一个集合
// 取出所有学生的成绩
List<Double> scoreList = list.stream().map(p -> p.getScore()).collect(Collectors.toList());
System.out.println("所有学生的成绩集合:" + scoreList);

// 将学生姓名集合串成字符串,用逗号分隔
String nameString = list.stream().map(p -> p.getName()).collect(Collectors.joining(","));
System.out.println("所有学生的姓名字符串:" + nameString);

// sorted排序
// 按学生成绩逆序排序 正序则不需要加.reversed()
filterList = list.stream().filter(p -> null != p.getScore()).sorted(Comparator.comparing(UserPo::getScore).reversed()).collect(Collectors.toList());
System.out.println("所有学生的成绩集合,逆序排序:");
filterList.stream().forEach(System.out::println);

System.out.println("按学生成绩归集:");
Map<Double, List<UserPo>> groupByScoreMap = list.stream().filter(p -> null != p.getScore())
.collect(Collectors.groupingBy(UserPo::getScore));
for (Map.Entry<Double, List<UserPo>> entry : groupByScoreMap.entrySet()) {
System.out.println("成绩:" + entry.getKey() + " 人数:" + entry.getValue().size());
}

// forEach
filterList.stream().forEach(p -> p.setScore(p.getScore() + 10));
System.out.println("及格人数太少,给每个人加10分");
filterList.stream().forEach(System.out::println);

// count
count = filterList.stream().filter(p -> p.getScore() >= 60).count();
System.out.println("最后及格人数" + count);

DoubleSummaryStatistics statistics = filterList.stream().mapToDouble(p -> p.getScore()).summaryStatistics();
System.out.println("列表中最大的数 : " + statistics.getMax());
System.out.println("列表中最小的数 : " + statistics.getMin());
System.out.println("所有数之和 : " + statistics.getSum());
System.out.println("平均数 : " + statistics.getAverage());

// 并行流 使用
count = list.parallelStream().filter(p -> null != p.getScore()).count();
System.out.println("并行流处理参加考试的学生人数:" + count);

}

}

文章目录
  1. 1. 简介
  2. 2.
  3. 3. PO代码
  4. 4. filter
  5. 5. map
  6. 6. sorted
  7. 7. forEach
  8. 8. collect
  9. 9. statistics
  10. 10. parallelStream
  11. 11. 完整代码