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结构。这种模式在实际项目中非常常见,掌握这些技巧能显著提升代码质量和开发效率。

相关推荐
海宇AI3 分钟前
零信任架构实战:基于海宇柠檬查出险-登记证构建自动化车抵贷核保网关
java·人工智能·架构·自动化
从零开始的嵌入式之旅43 分钟前
day44
arm开发·经验分享·笔记·嵌入式硬件
cfm_29142 小时前
单例模式详解
java
我叫张土豆2 小时前
本体论、DDD、SDD、TDD:AI 编程时代的四层认知栈
java·人工智能
白远山2 小时前
家政服务家政社区派单实战:调度系统架构设计与实现指南
java·开发语言·小程序·架构·需求分析
海南java第二人2 小时前
从诞生到回收:JVM对象生命周期与垃圾回收全链路解析
java
SL_staff2 小时前
JVS-Logic:从页面配置工具到企业级业务逻辑中枢的技术演进
java·算法·全栈
DevRay3 小时前
Java 21虚拟线程深度实战:告别线程池焦虑,百万并发吞吐量直接翻倍(原理+代码+避坑)
java·开发语言
forestsea3 小时前
从零构建 Java 智能体 RAG 系统:Milvus 向量数据库实战指南
java·数据库·milvus
lifewange3 小时前
VSCode怎么运行java
java·ide·vscode