前提:以下基于 List<Student> 列表进行举例,大家实际使用进行举一反三即可。大同小异,Java8 的流式计算功能很强大,需要大家实际应用中逐渐挖掘更高级的用法。
Student 类大致如下:
public class Student {
/**
* 学号
*/
private String number;
/**
* 姓名
*/
private String name;
/**
* 性别
*/
private String gender;
/**
* 分数
*/
private BigDecimal score;
// 以下 Getter 和 Setter 方法省略
...
}
1. 过滤。比如你要在学生列表中过滤出性别为男性的学生,并形成一个新的列表。
studentList
// 开启流式计算, 所有要使用流式计算的都需要先开启,比如另外一种场景 Stream.of(数组)
.stream()
// filter方法即为过滤
.filter(v -> "男".equals(v.getGender()))
// 将结果转成 list
.collect(Collectors.toList())
2.List转Map。比如学号对于学生来说是一一对应的,想通过学号能够直接获取到对应的学生,这时候我们可以使用 Map 的键值对来进行实现,如果使用 List 每次还要遍历获取。
studentList
.stream()
// Collectors.toMap() 有3个重载,建议使用3个或4个参数的重载方法
// 1参:转化后Map的key; 2参:转化后Map的值; 3参:如果key值有重复,使用什么覆盖策略; 4参:转化后Map的类型
// Student::getNumber 是双冒号用法, 可以通过 类名::方法名 指定调用哪个方法获取到结果
// v -> v 表示直接使用 List 中的对象作为实例; 如果使用学生名称作为值, 则可以 v -> v.getName()
// (v1, v2) -> v2 表示如果有相同的key,则使用后面的值覆盖key已经有的值。如果(v1, v2) ->v1, 则不覆盖,保留key已经有的值。Map相同的key只能有一个。(注意:如果不指定覆盖策略,遇到相同key会抛异常)
.collect(Collectors.toMap(Student::getNumber, v -> v, (v1, v2) -> v2))
3.获取List中的对象某个字段形成列表。比如需要获取学生的名字列表。
studentList
.stream()
// 将列表中的学生对象映射成名字字段
.map(Student::getName)
// 可以对结果进行去重
.distinct()
.collect(Collectors.toList());
4.想获取学号为 123 的学生。
studentList
.stream()
// 过滤出学号为 123 的学生
.filter(v -> "123".equals(v.getNumber()))
// 假如 过滤出的结果如果有多个,但我们只需要一个可以使用以下方法,表示返回第一个找到的。
// 还可以返回任意一个,使用 findAny()
.findFirst()
// 如果找不到则返回 null
.orElse(null)
5. 分数是 BigDecimal 类型,怎么求和?
student
.stream()
// 先把实体都映射成分数字段
.map(v -> v.getScore())
// 这个方法用得不多,它的常用方法都被分装起来了,比如sum(), count(), min(), max()等
// reduce 有三个重载方法,以下只介绍2个参数的
// 1参:初始值; 2参:每一个元素和前一个结果如何运算
.reduce(BigDecimal.ZERO, BigDecimal::add)
// 如果 List 中是 基本类型的包装类型, 比如 List<Integer> 则更方便。
list
.stream()
// 映射成 int 类型
.mapToInt(Integer::intValue)
// 求和。计数可以使用 count(), 取最小可以使用 min(), 求平均值可使用 average()等等
.sum()
6. 学生按性别进行分组。
studentList
.stream()
// 使用 groupingBy 进行分组
.collect(Collectors.groupingBy(Student::getGender))
// 如果要按分数进行分组呢?比如成绩<60的分到F组,60<=成绩<80分到C组,80<=成绩<90分到B组, 90<=成绩分到A组
final BigDecimal SIXTY = new BigDecimal("60");
final BigDecimal EIGHTY = new BigDecimal("80");
final BigDecimal NINETY = new BigDecimal("90");
Map<String, List<Student>> map = list
.stream()
// groupingBy 1参返回的会作为结果Map中的key
.collect(Collectors.groupingBy(item -> {
if (SIXTY.compareTo(item.getScore()) > 0) {
// (, 60)
return "F";
}
if (SIXTY.compareTo(item.getScore()) <= 0
&& EIGHTY.compareTo(item.getScore()) > 0) {
// [60, 80)
return "C";
}
if (EIGHTY.compareTo(item.getScore()) <= 0
&& NINETY.compareTo(item.getScore()) > 0) {
// [80, 90)
return "B";
}
if (NINETY.compareTo(item.getScore()) <= 0) {
// [90, )
return "A";
}
return "其他";
}));
额外内容:
如果使用了流式计算,怎么进行调试?Idea可以使用如下方法:
1. 打断点,在需要调试的Stream上 stream() 行 或 之后的行 上进行断点标记。
2. 执行到断点后,点击 Idea 调试窗口(Debug) 上的 Trace Current Stream Chain 即可。