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

如何用Java 8优雅实现从List<Chore>生成<Chore, Long>的出现次数统计Map

解决方法

要生成以Chore对象为键的Map<Chore, Long>,核心在于让Map把id相同的Chore识别为同一个键,具体分两种场景处理:


场景1:可以修改Chore类(推荐方案)

Java中Map判断键是否相等依赖equals()和hashCode()方法,默认的Object实现是比较对象引用,所以必须重写这两个方法,仅基于id字段判断对象相等:

import java.util.Objects;

public class Chore {
    private String id;
    private String name;
    private String date;

    // 构造器、getter、setter省略

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Chore chore = (Chore) o;
        return Objects.equals(id, chore.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

修改完成后,直接用Function.identity()作为分组依据,配合Collectors.counting()即可得到目标Map:

Map<Chore, Long> choreCountMap = choreList.stream()
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

此时id相同的Chore会被识别为同一个键,统计结果完全符合需求——比如id为"1"的Chore对应值3,id为"2"的对应值2。


场景2:无法修改Chore类

如果不能改动原Chore类的equals和hashCode,可以先按id分组统计次数,再将每组的第一个Chore实例作为键映射到对应次数:

Map<Chore, Long> choreCountMap = choreList.stream()
    // 先按id分组,得到<id, List<Chore>>结构
    .collect(Collectors.groupingBy(Chore::getId))
    .entrySet()
    .stream()
    // 把每个id对应的第一个Chore实例和列表大小(出现次数)转成Entry
    .map(entry -> new AbstractMap.SimpleEntry<>(entry.getValue().get(0), (long) entry.getValue().size()))
    // 收集为最终的Map
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

这种方式无需修改原类,缺点是每个分组取的是第一个Chore实例作为代表键,若需要指定实例可调整get(0)的逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 05:24:07