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

Java Stream分组需求:按母亲姓名分组,以Name为Map键

解决方案:按MotherName分组并以Name为键的Map

这个问题我之前也碰到过,核心是要保持按母亲名字分组的逻辑不变,但把分组结果的键从String换成Name对象。这里分两种常见场景给出实现方式:


场景1:仅以MotherName作为分组判断依据(忽略Name的其他字段)

如果只要母亲名字相同,就归为同一组,且组的键是一个仅包含该母亲名字的Name实例,你需要先修改Name类,确保它的equals()和hashCode()只基于motherName字段(因为HashMap依赖这两个方法判断键是否相等),再调整分组逻辑:

第一步:修改Name类

import java.util.Objects;

public class Name {
    private String name;
    private String fatherName;
    private String motherName;

    // 原有构造方法、getter/setter省略

    // 新增静态工厂方法,快速创建仅含motherName的Name实例
    public static Name fromMotherName(String motherName) {
        Name nameInstance = new Name();
        nameInstance.setMotherName(motherName);
        return nameInstance;
    }

    // 重写equals,仅比较motherName
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Name name = (Name) o;
        return Objects.equals(motherName, name.motherName);
    }

    // 重写hashCode,仅基于motherName
    @Override
    public int hashCode() {
        return Objects.hash(motherName);
    }
}

第二步:调整分组代码

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

Collection<Person> persons = ...; // 你的Person集合

Map<Name, List<Person>> group = persons.stream()
    .collect(Collectors.groupingBy(
        // 分组函数返回Name对象,而非字符串
        person -> Name.fromMotherName(person.getName().getMotherName())
    ));

场景2:以MotherName分组,但键保留组内第一个Person的完整Name对象

如果你希望组的键是该分组下第一个出现的Person的完整Name实例(保留name、fatherName等所有字段),可以先按motherName字符串分组,再转换键的类型:

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

Collection<Person> persons = ...; // 你的Person集合

Map<Name, List<Person>> group = persons.stream()
    // 先按motherName字符串分组,同时把每组转换成<Name, List<Person>>的Entry
    .collect(Collectors.groupingBy(
        p -> p.getName().getMotherName(),
        Collectors.collectingAndThen(
            Collectors.toList(),
            personList -> new AbstractMap.SimpleEntry<>(
                personList.get(0).getName(), // 取第一个Person的Name作为键
                personList
            )
        )
    ))
    // 把Entry集合转换成最终的Map
    .values()
    .stream()
    .collect(Collectors.toMap(
        AbstractMap.SimpleEntry::getKey,
        AbstractMap.SimpleEntry::getValue
    ));

注意事项

  • 场景2中如果分组后的列表为空(实际Stream分组不会出现),personList.get(0)会抛出IndexOutOfBoundsException,可以加个非空判断。
  • 如果你的Name类已经有合理的equals()和hashCode()实现(比如比较所有字段),那场景1的修改不适用,需要用场景2的方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 03:43:25