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

相关推荐
VX:Fegn089513 分钟前
计算机毕业设计|基于springboot + vue智慧医药系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
两个蝴蝶飞5 小时前
Java量化系列(四):实现自选股票维护功能
java·经验分享
短剑重铸之日6 小时前
7天读懂MySQL|Day 5:执行引擎与SQL优化
java·数据库·sql·mysql·架构
酒九鸠玖7 小时前
Java--多线程
java
Dreamboat-L7 小时前
云服务器上部署nginx
java·服务器·nginx
长安er7 小时前
LeetCode215/347/295 堆相关理论与题目
java·数据结构·算法·leetcode·
cici158748 小时前
C#实现三菱PLC通信
java·网络·c#
k***92169 小时前
【C++】继承和多态扩展学习
java·c++·学习
weixin_440730509 小时前
java结构语句学习
java·开发语言·学习
魂万劫9 小时前
如何在虚拟机VM上|Linux环境内安装windows
linux·运维·服务器·windows