Java Stream 数据处理笔记:从嵌套集合中过滤特定类别的Map

Java Stream 数据处理笔记:从嵌套集合中过滤特定类别的Map

在Java开发中,我们经常需要处理嵌套集合结构(如List<List<WarehouseDto>>),并从中提取特定类别的数据构建Map。本文将详细讲解如何使用Stream API高效实现这一需求。

一、问题场景描述

假设我们有一个仓库组列表List<WarehouseGroup>,每个仓库组包含多个仓库List<WarehouseDto>。我们需要:

  1. 将嵌套结构扁平化为单一仓库流
  2. 过滤出特定类别的仓库(如官方仓PLATFORM
  3. 构建以仓库ID为键、仓库对象为值的Map
java 复制代码
// 原始数据结构
class WarehouseGroup {
    private List<WarehouseDto> warehouses;
    // getter/setter
}

class WarehouseDto {
    private Long id;
    private WarehouseCategory category;
    // getter/setter
}

enum WarehouseCategory {
    PLATFORM,   // 官方仓
    THIRD_PARTY // 第三方仓
}

二、基础实现:无过滤的Map构建

首先实现基本功能,不添加过滤条件:

java 复制代码
Map<Long, WarehouseDto> warehouseMap = warehouseGroupList.stream()
    .map(WarehouseGroup::getWarehouses)  // 转换为List<WarehouseDto>的流
    .flatMap(List::stream)               // 扁平化为WarehouseDto流
    .collect(Collectors.toMap(
        WarehouseDto::getId,             // 键:仓库ID
        Function.identity(),             // 值:仓库对象本身
        (existing, replacement) -> existing, // 冲突处理:保留已有值
        LinkedHashMap::new               // Map实现:保持插入顺序
    ));

三、添加过滤条件:只保留官方仓

在构建Map前添加过滤条件,只保留PLATFORM类别的仓库:

java 复制代码
Map<Long, WarehouseDto> platformWarehouseMap = warehouseGroupList.stream()
    .map(WarehouseGroup::getWarehouses)
    .flatMap(List::stream)
    // 关键过滤步骤:只保留官方仓
    .filter(warehouse -> WarehouseCategory.PLATFORM.equals(warehouse.getCategory()))
    .collect(Collectors.toMap(
        WarehouseDto::getId,
        Function.identity(),
        (existing, replacement) -> existing,
        LinkedHashMap::new
    ));

四、最佳实践与优化技巧

1. 空值安全处理

避免空指针异常,添加多层空值检查:

java 复制代码
Map<Long, WarehouseDto> safePlatformMap = warehouseGroupList.stream()
    .filter(Objects::nonNull) // 过滤null的WarehouseGroup
    .map(WarehouseGroup::getWarehouses)
    .filter(Objects::nonNull) // 过滤null的warehouses列表
    .flatMap(List::stream)
    .filter(Objects::nonNull) // 过滤null的WarehouseDto
    .filter(warehouse -> WarehouseCategory.PLATFORM.equals(
        Optional.ofNullable(warehouse.getCategory()).orElse(null)
    ))
    .collect(Collectors.toMap(...));

2. 性能优化:先过滤后映射

遵循"先过滤,后映射"原则,减少不必要的计算:

java 复制代码
// 优化版:先过滤出官方仓,再提取ID
Map<Long, WarehouseDto> optimizedMap = warehouseGroupList.stream()
    .map(WarehouseGroup::getWarehouses)
    .flatMap(List::stream)
    .filter(warehouse -> 
        warehouse != null && 
        WarehouseCategory.PLATFORM.equals(warehouse.getCategory())
    )
    .collect(Collectors.toMap(WarehouseDto::getId, Function.identity()));

3. 并行处理大数据量

当数据量较大时,使用并行流提升性能:

java 复制代码
Map<Long, WarehouseDto> parallelMap = warehouseGroupList.parallelStream()
    .map(WarehouseGroup::getWarehouses)
    .flatMap(List::stream)
    .filter(warehouse -> WarehouseCategory.PLATFORM.equals(warehouse.getCategory()))
    .collect(Collectors.toConcurrentMap( // 使用线程安全的ConcurrentHashMap
        WarehouseDto::getId,
        Function.identity(),
        (existing, replacement) -> existing
    ));

五、完整代码示例

java 复制代码
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class WarehouseStreamDemo {

    public Map<Long, WarehouseDto> createPlatformWarehouseMap(
        List<WarehouseGroup> warehouseGroupList
    ) {
        return warehouseGroupList.stream()
            .filter(Objects::nonNull)
            .map(WarehouseGroup::getWarehouses)
            .filter(Objects::nonNull)
            .flatMap(List::stream)
            .filter(Objects::nonNull)
            .filter(warehouse -> 
                WarehouseCategory.PLATFORM.equals(
                    Optional.ofNullable(warehouse.getCategory()).orElse(null)
                )
            )
            .collect(Collectors.toMap(
                WarehouseDto::getId,
                Function.identity(),
                (existing, replacement) -> existing,
                LinkedHashMap::new
            ));
    }
    
    // 实体类定义
    static class WarehouseGroup {
        private List<WarehouseDto> warehouses;
        public List<WarehouseDto> getWarehouses() { return warehouses; }
    }
    
    static class WarehouseDto {
        private Long id;
        private WarehouseCategory category;
        public Long getId() { return id; }
        public WarehouseCategory getCategory() { return category; }
    }
    
    enum WarehouseCategory {
        PLATFORM,   // 官方仓
        THIRD_PARTY // 第三方仓
    }
}

六、关键点总结

  1. 扁平化嵌套结构 :使用flatMapList<List<T>>转换为Stream<T>
  2. 过滤条件放置:在收集前进行过滤,避免处理不必要的数据
  3. 空值安全:多层空值检查防止NPE
  4. 性能优化
    • 先过滤后映射
    • 大数据量使用并行流
    • 使用合适的Map实现(如ConcurrentHashMap用于并行流)
  5. 冲突处理:指定合并函数处理键冲突

通过以上方法,您可以高效地从复杂嵌套结构中提取并过滤特定类别的数据,构建所需的Map结构。这种模式在实际项目中非常常见,掌握这些技巧能显著提升代码质量和开发效率。

相关推荐
lee_curry5 小时前
第四章 jvm中的垃圾回收器
java·jvm·垃圾收集器
码途漫谈6 小时前
Easy-Vibe开发篇阅读笔记(四)——前端开发之结合 Agent Skills 美化界面
人工智能·笔记·ai·开源·ai编程
John_ToDebug6 小时前
隐于无形,触手可及:Chrome 互动滚动条的六个设计密码
chrome·windows·ui
九转成圣6 小时前
Java 性能优化实战:如何将海量扁平数据高效转化为类目字典树?
java·开发语言·json
思茂信息7 小时前
CST软件如何进行参数化扫描?
运维·开发语言·javascript·windows·ecmascript·软件工程·软件需求
直奔標竿7 小时前
Java开发者AI转型第二十七课!Spring AI 个人知识库实战(六)——全栈闭环收官,解锁前端流式渲染终极技巧
java·开发语言·前端·人工智能·后端·spring
金銀銅鐵7 小时前
[java] 编译之后的记录类(Record Classes)长什么样子(上)
java·jvm·后端
开发者联盟league8 小时前
在windows上安装和运行rocketmq
windows·rocketmq
糖炒栗子03268 小时前
【笔记】高分卫星影像 TIF 切片处理
笔记
Nice_Fold9 小时前
Kubernetes DaemonSet、StatefulSet与Service(自用笔记)
笔记·容器·kubernetes