Java Lambda 分片(分组 / 分区)超详细讲解

在 Java 中,Lambda 结合 Stream API 实现的分片 ,本质就是把一个集合 / 流,按照指定规则拆分成多个小集合,最核心的两个 API 是:

  • Collectors.groupingBy()分组(按任意条件分成 N 组,key = 分组条件,value = 对应元素列表)
  • Collectors.partitioningBy()分区(特殊分组,只能分成 true/false 两组)

日常说的「分片」,90% 指 groupingBy 分组,10% 指 partitioningBy 分区,我会用最通俗的语言 + 实战代码讲透。


一、先搞懂:什么是 Lambda 分片?

给你一个集合,比如 List<Student>,你想:

  1. 年龄 分成:18 岁一组、19 岁一组、20 岁一组 → groupingBy 分组
  2. 是否成年 分成:成年一组、未成年一组 → partitioningBy 分区

这就是 Lambda 分片一行代码,用流式 + Lambda 表达式,快速拆分集合,不用写循环、if-else。


二、核心 API 1:Collectors.groupingBy () 【最常用:分组分片】

1. 作用

按照 自定义的分类规则(Lambda 函数) ,把流分成 多个组 ,返回 Map<分类结果, List<原元素>>

2. 3 种常用用法(必掌握)

(1)基础分组:单条件分片
java 复制代码
// 实体类
@Data
@AllArgsConstructor
class Student {
    private String name;
    private int age;
    private String gender;
}

// 测试数据
List<Student> list = Arrays.asList(
    new Student("张三", 18, "男"),
    new Student("李四", 19, "男"),
    new Student("王五", 18, "女"),
    new Student("赵六", 19, "女")
);

// ====================== Lambda 分组分片 ======================
// 按年龄分组(key=年龄,value=对应学生列表)
Map<Integer, List<Student>> groupByAge = list.stream()
    .collect(Collectors.groupingBy(Student::getAge)); // Lambda 简写

// 等价 Lambda 完整写法
// .collect(Collectors.groupingBy(s -> s.getAge()));

结果

  • key=18 → 张三,王五
  • key=19 → 李四,赵六

(2)多级分组:嵌套分片(先按性别,再按年龄)
java 复制代码
// 先按性别分,再按年龄分 → 双层 Map
Map<String, Map<Integer, List<Student>>> multiGroup = list.stream()
    .collect(Collectors.groupingBy(
        Student::getGender,       // 第一层分组:性别
        Collectors.groupingBy(Student::getAge) // 第二层分组:年龄
    ));

结果

  • 男 → {18=张三, 19=李四}
  • 女 → {18=王五, 19=赵六}

(3)分组 + 聚合:分片后统计(数量、总和、平均值)

分片后不只想要列表,还想要每组数量、总和、平均值

java 复制代码
// 按性别分组,统计每组人数
Map<String, Long> groupCount = list.stream()
    .collect(Collectors.groupingBy(
        Student::getGender,
        Collectors.counting() // 聚合:计数
    ));

// 按性别分组,统计平均年龄
Map<String, Double> groupAvgAge = list.stream()
    .collect(Collectors.groupingBy(
        Student::getGender,
        Collectors.averagingInt(Student::getAge) // 聚合:平均值
    ));

三、核心 API 2:Collectors.partitioningBy () 【分区:二分片】

1. 作用

只能分成两组true 一组、false 一组,返回 Map<Boolean, List<原元素>>

适用场景:只有两种结果的分片(是 / 否、通过 / 不通过、成年 / 未成年)。

2. 实战代码

java 复制代码
// 按【是否成年】分片(true=成年,false=未成年)
Map<Boolean, List<Student>> partition = list.stream()
    .collect(Collectors.partitioningBy(s -> s.getAge() >= 18));

// 获取成年学生
List<Student> adults = partition.get(true);
// 获取未成年学生
List<Student> minors = partition.get(false);

3. 特点

  • 永远返回 两个 keytruefalse(哪怕对应列表为空)
  • 条件必须是 返回 boolean 的 Lambda

四、groupingBy 和 partitioningBy 对比(一看就懂)

表格

特性 groupingBy (分组) partitioningBy (分区)
分片结果 任意 N 组 固定 2 组(true/false)
返回类型 Map<K, List<T>> Map<Boolean, List<T>>
Lambda 返回值 任意类型(对象、数值等) 必须 boolean
空分组 不会生成空 key 一定有 true/false 两个 key
适用场景 多条件分类、复杂分片 二分类、是非判断

五、Lambda 分片的完整实战示例(可直接运行)

java 复制代码
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class LambdaSplitDemo {
    public static void main(String[] args) {
        List<Student> students = Arrays.asList(
            new Student("小明", 17, "男"),
            new Student("小红", 18, "女"),
            new Student("小刚", 19, "男"),
            new Student("小丽", 18, "女")
        );

        // 1. 分组分片:按年龄
        Map<Integer, List<Student>> groupByAge = students.stream()
                .collect(Collectors.groupingBy(Student::getAge));
        System.out.println("按年龄分组:" + groupByAge);

        // 2. 分区分片:是否成年
        Map<Boolean, List<Student>> partitionByAdult = students.stream()
                .collect(Collectors.partitioningBy(s -> s.getAge() >= 18));
        System.out.println("是否成年分区:" + partitionByAdult);

        // 3. 分组+统计:按性别统计人数
        Map<String, Long> groupCount = students.stream()
                .collect(Collectors.groupingBy(Student::getGender, Collectors.counting()));
        System.out.println("按性别统计人数:" + groupCount);
    }
}

@Data
@AllArgsConstructor
class Student {
    private String name;
    private int age;
    private String gender;
}

关键记忆点(背会就能写代码)

1. 一句话区分两个分片 API

  • 多结果分片 → 用 groupingBy(Lambda 返回任意值)
  • 二结果分片 → 用 partitioningBy(Lambda 必须返回 boolean)

2. 核心语法模板(直接套用)

java 复制代码
// 分组分片
Map<结果类型, List<元素>> 变量 = 集合.stream()
    .collect(Collectors.groupingBy( Lambda 分组条件 ));

// 分区分片
Map<Boolean, List<元素>> 变量 = 集合.stream()
    .collect(Collectors.partitioningBy( Lambda 布尔条件 ));

3. 必背 3 个分组聚合用法

  • Collectors.counting():统计每组数量
  • Collectors.summingInt():统计每组数值和
  • Collectors.averagingInt():统计每组平均值

4. 核心特性

  1. 分片是 Stream 终止操作 ,必须用 collect() 接收
  2. 分组返回 Map,key 是分组条件结果,value 是元素列表
  3. 分区永远有 true/false 两个 key,分组没有空 key
  4. Lambda 写法:对象::get方法 等价 s -> s.getXXX()

总结

  1. Java Lambda 分片 = Stream + Collectors 分组 / 分区,替代繁琐循环
  2. groupingBy:通用多组分片,工作中最常用
  3. partitioningBy:专用二分片,简单场景使用
  4. 记忆核心:多组用 groupingBy,二组用 partitioningBy
相关推荐
阿汤猫66614 小时前
基于OpenCode的Harness架构实战验收指南v3.0 (windows系统)
windows·prompt
阿汤猫66615 小时前
基于OpenCode的Harness架构实战v2.2(windows系统)
windows·prompt
xiaoshuaishuai817 小时前
C# AvaloniaUI 资源找不到报错
java·服务器·前端·windows·c#
思麟呀17 小时前
C++11并发编程:call_once一次性执行+atomic原子类型+CAS无锁编程+自旋锁
linux·开发语言·jvm·c++·windows
爱讲故事的18 小时前
操作系统第一讲复习:为什么学习操作系统,以及操作系统到底在做什么?
linux·开发语言·windows·学习·ubuntu·c#
韩曙亮1 天前
【错误记录】flutter pub get 执行报错 ( 打开 Windows 开发者模式 )
windows·flutter
一个人旅程~1 天前
如何让bootcamp-win10中的触摸板像macbook中一样丝滑原生效果?
windows·经验分享·macos·电脑
zyl837211 天前
Python 四大核心数据结构:列表、字典、元组、集合
数据结构·windows·python
霸道流氓气质1 天前
Spring AI Alibaba + Ollama Function Calling 项目完整指南
人工智能·windows·spring