You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过单次Stream将自定义对象多String属性收集为Map<String,List<String>>

实现方案

可以通过单次流操作实现需求,核心思路是先把每个TeamMates实例拆解为「属性名-属性值」的键值对流,再通过Collectors.groupingBy聚合即可,不需要多次遍历集合,也不需要手动用forEach操作容器。

固定属性场景(推荐,性能更稳定)

如果TeamMates的属性固定,直接硬编码属性名即可:

import java.util.AbstractMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

// 你的业务逻辑
List<TeamMates> teamMatesList = ...; // 源数据列表
Map<String, List<String>> result = teamMatesList.stream()
    // 把每个对象拆为3个属性键值对,展开为流
    .flatMap(teamMate -> List.of(
        new AbstractMap.SimpleEntry<>("playerFirstName", teamMate.getPlayerFirstName()),
        new AbstractMap.SimpleEntry<>("playerLastName", teamMate.getPlayerLastName()),
        new AbstractMap.SimpleEntry<>("playerMaidenName", teamMate.getPlayerMaidenName())
    ).stream())
    // 按属性名分组,收集对应属性值到列表
    .collect(Collectors.groupingBy(
        Map.Entry::getKey,
        Collectors.mapping(Map.Entry::getValue, Collectors.toList())
    ));

如果你使用Java 9及以上版本,可以用Map.entry()替代AbstractMap.SimpleEntry,代码更简洁:

.flatMap(teamMate -> List.of(
    Map.entry("playerFirstName", teamMate.getPlayerFirstName()),
    Map.entry("playerLastName", teamMate.getPlayerLastName()),
    Map.entry("playerMaidenName", teamMate.getPlayerMaidenName())
).stream())

动态属性场景

如果后续会频繁新增String类型的属性,不想每次修改硬编码的键值对列表,可以用反射动态读取所有String属性:

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

List<TeamMates> teamMatesList = ...;
Map<String, List<String>> result = teamMatesList.stream()
    .flatMap(teamMate -> Arrays.stream(TeamMates.class.getDeclaredFields())
        // 只筛选String类型的属性
        .filter(field -> field.getType() == String.class)
        // 开启私有属性访问权限
        .peek(field -> field.setAccessible(true))
        .map(field -> {
            try {
                return new AbstractMap.SimpleEntry<>(field.getName(), (String) field.get(teamMate));
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        })
    )
    .collect(Collectors.groupingBy(
        Map.Entry::getKey,
        Collectors.mapping(Map.Entry::getValue, Collectors.toList())
    ));

注意反射方案存在一定性能损耗,且如果类的属性有访问控制限制可能抛出异常,属性固定的场景优先选择硬编码方案。

内容的提问来源于stack exchange,提问作者Vijay Manohar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 16:27:03