Java中的stream流分组示例详解

 更新时间:2025年08月19日 16:23:38   作者:不做光头强  
Java8 Stream API以函数式风格处理集合数据,支持分组、统计等操作,可按单/多字段分组,使用String、Map.Entry或Java16 record定义键,并获取数量、属性集合、极值等信息,本文给大家介绍Java中的stream流分组,感兴趣的朋友跟随小编一起看看吧

什么是stream流

Java 8引入的Stream API是处理集合数据的一种全新方式,它代表了对数据元素序列进行函数式操作的抽象。Stream不是数据结构,而是一种高级的数据处理工具,允许你以声明式的方式处理数据集合,类似于SQL语句操作数据库。

Stream的核心特点:

  • 声明式编程:只需说明"做什么"而非"如何做",代码更简洁易读
  • 函数式风格:与Lambda表达式完美结合,操作更灵活
  • 管道操作:多个操作可以连接起来形成数据处理流水线
  • 内部迭代:不同于集合的外部迭代(使用for-each),Stream在内部处理迭代过程
  • 延迟执行:中间操作不会立即执行,只有遇到终结操作才会触发计算
  • 不可复用:一个Stream只能被消费一次

1、根据某个字段分组

 // 按 department 字段分组
        Map<String, List<User>> groupedByDept = users.stream()
            .collect(Collectors.groupingBy(User::getDepartment));

2、按多个字段分组(组合分组)

1、方法一:使用 String 拼接作为分组 key(简单但不够灵活)

Map<String, List<User>> grouped = users.stream()
    .collect(Collectors.groupingBy(
        user -> user.getDepartment() + "-" + user.getJobTitle()
    ));

2、使用 Map.Entry(Java 8+ 就支持):

Map<Map.Entry<String, String>, List<User>> grouped = users.stream()
    .collect(Collectors.groupingBy(
        user -> Map.entry(user.getDepartment(), user.getJobTitle())
    ));

        这样 key 是一个 Map.Entry<部门, 职位>,可以唯一确定一个组合

3、使用 record(Java 16+):

// 定义一个记录类作为分组 key
record DeptJobKey(String department, String jobTitle) {}
Map<DeptJobKey, List<User>> grouped = users.stream()
    .collect(Collectors.groupingBy(
        user -> new DeptJobKey(user.getDepartment(), user.getJobTitle())
    ));

3、分组后获取其他统计信息

1、分组后统计每组的数量

Map<String, Long> countByDept = users.stream()
    .collect(Collectors.groupingBy(
        User::getDepartment,
        Collectors.counting()  // 统计每个部门的用户数
    ));

2、分组后获取每组中的某个属性集合,比如所有部门下的用户名

Map<String, List<String>> namesByDept = users.stream()
    .collect(Collectors.groupingBy(
        User::getDepartment,
        Collectors.mapping(User::getName, Collectors.toList()) // 只提取 name 字段
    ));

3、分组后求每组的某个属性的最大值 / 最小值 / 平均值

Map<String, Optional<Integer>> maxAgeByDept = users.stream()
    .collect(Collectors.groupingBy(
        User::getDepartment,
        Collectors.mapping(User::getAge, Collectors.maxBy(Comparator.naturalOrder()))
    ));
// 或者更直观地使用 Collectors.maxBy / averagingInt 等
//或者使用 Collectors.summarizingInt 做综合统计
Map<String, IntSummaryStatistics> ageStatsByDept = users.stream()
    .collect(Collectors.groupingBy(
        User::getDepartment,
        Collectors.summarizingInt(User::getAge)  // 统计年龄:count, sum, min, max, avg
    ));

4、自定义分组key

Map<String, List<User>> collect = javaList.stream().collect(Collectors.groupingBy(user -> {
            String id = user.getId();
            return (StringUtils.isEmpty(id)) ? "empty" : "notEmpty"; // 如果为 null,返回empty,不为空notEmpty
        }));

到此这篇关于Java的stream流分组的文章就介绍到这了,更多相关Java stream流分组内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • redis做服务间通信工具的项目示例

    redis做服务间通信工具的项目示例

    Redis是一种高效的服务间通信工具,它以键值对的形式存储数据,并支持多种数据类型和丰富的操作,本文主要介绍了redis做服务间通信工具的项目示例,感兴趣的可以了解一下
    2023-08-08
  • Java中NoClassDefFoundError异常的原因及解决方法

    Java中NoClassDefFoundError异常的原因及解决方法

    在 Java 开发中,java.lang.NoClassDefFoundError 是运行时异常中最常见的问题之一,它通常出现在程序编译成功后,却在运行时因 JVM 无法找到某个类的定义 而抛出,本文给大家介绍了Java中NoClassDefFoundError异常的原因及解决方法,需要的朋友可以参考下
    2025-05-05
  • controller接口跳转到另一个controller接口的实现

    controller接口跳转到另一个controller接口的实现

    这篇文章主要介绍了controller接口跳转到另一个controller接口的实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • Java求素数和最大公约数的简单代码示例

    Java求素数和最大公约数的简单代码示例

    这篇文章主要介绍了Java求素数和最大公约数的简单代码示例,其中作者创建的Fraction类可以用来进行各种分数运算,需要的朋友可以参考下
    2015-09-09
  • Java FTP协议实现文件下载功能

    Java FTP协议实现文件下载功能

    FTP(File Transfer Protocol)就是文件传输协议。通过FTP客户端从远程FTP服务器上拷贝文件到本地计算机称为下载,将本地计算机上的文件复制到远程FTP服务器上称为上传,上传和下载是FTP最常用的两个功能
    2022-11-11
  • springboot整合mybatis-plus实现多表分页查询的示例代码

    springboot整合mybatis-plus实现多表分页查询的示例代码

    这篇文章主要介绍了springboot整合mybatis-plus实现多表分页查询的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • 浅谈Spring Data如何简化数据操作的方法

    浅谈Spring Data如何简化数据操作的方法

    这篇文章主要介绍了看Spring Data如何简化数据操作的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-04-04
  • 深入解析Java中的数据类型与变量

    深入解析Java中的数据类型与变量

    这篇文章主要介绍了深入解析Java中的数据类型与变量,是Java入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • Java并发编程之线程状态介绍

    Java并发编程之线程状态介绍

    这篇文章主要介绍了Java并发编程之线程状态,当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态,下面和小编一起进入文章了解具体的相关介绍吧
    2022-04-04
  • Java代码中4种字符串拼接方式分析

    Java代码中4种字符串拼接方式分析

    本文主要介绍了Java代码中4种字符串拼接方式分析,主要介绍了“+”号、StringBuilder、StringJoiner、String#join,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02

最新评论