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

Java 8 Stream groupingBy疑问:如何按City对象而非邮编字符串分组

嘿,这个问题我之前做项目的时候也碰到过,太懂这种纠结的感觉了!咱们来一步步解决它:

问题根源

你直接用Collectors.groupingBy(Person::getCity)失效,本质原因是Java默认的equals()和hashCode()方法是基于对象引用的——哪怕两个City对象的postalcode完全一样,只要它们是不同的实例,就会被groupingBy当成不同的分组key,自然达不到按邮编分组的效果。

而用person -> person.city.postalcode分组,得到的是Map<String, List<Person>>,这是因为key变成了字符串类型的邮编,不是你想要的City对象。


解决方案1:给City类重写equals()和hashCode()(推荐)

如果业务上postalcode是City的唯一标识(或者你希望只要邮编相同就归为同一组),那直接给City类重写这两个方法,让它们只基于postalcode判断相等:

import java.util.Objects;

public class City {
    private String postalcode;
    // 其他字段(比如cityName等)

    // 重写equals,只比较postalcode
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        City city = (City) o;
        return Objects.equals(postalcode, city.postalcode);
    }

    // 重写hashCode,基于postalcode生成哈希值
    @Override
    public int hashCode() {
        return Objects.hash(postalcode);
    }

    // getter、setter等方法
}

重写之后,直接用City对象分组就可以得到你想要的结果:

Map<City, List<Person>> groupedByCity = personList.stream()
    .collect(Collectors.groupingBy(Person::getCity));

现在只要两个City的邮编相同,就会被groupingBy识别为同一个key,对应的Person会被分到同一组里。


解决方案2:不修改City类的情况下转换Map

如果因为某些原因不能修改City类(比如它是第三方库的类,或者其他业务逻辑依赖原有的引用相等判断),那可以先按邮编分组,再把结果转换成Map<City, List<Person>>:

Map<City, List<Person>> groupedByCity = personList.stream()
    // 先按邮编分组得到Map<String, List<Person>>
    .collect(Collectors.groupingBy(p -> p.getCity().getPostalcode()))
    // 把每个entry的key转换成City对象(这里取每组第一个Person的City作为key)
    .entrySet().stream()
    .collect(Collectors.toMap(
        entry -> entry.getValue().get(0).getCity(),
        Map.Entry::getValue
    ));

⚠️ 注意:这种方法要确保同一邮编对应的City对象在其他字段上是一致的,否则如果同一邮编下的City有不同的名称或其他属性,取第一个City作为key可能不符合你的预期。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:04:44