[编程] Java8 Stream(流式计算) 常见的一些用法汇总

本文介绍了Java8的流式计算特性,包括过滤学生列表、将列表转换为Map、获取特定字段列表、查找特定条件的对象、分数求和以及按条件分组。示例代码详细展示了如何利用Stream API进行高效操作,帮助读者理解并运用到实际项目中。
摘要由CSDN通过智能技术生成

前提:以下基于 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 即可。

作者有话说:如果有幸帮助到你,麻烦给个赞,给个收藏,给个关注,感谢!你的赞,收藏和关注是我的动力源泉

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值