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

Java中groupingBy与mapping的正确实现:统计各年级编程爱好学生数

需求与问题

我有一份学生成绩JSON数据,需要统计每个年级(standard)中爱好包含programming的学生数量。但我写的Java代码无法实现需求,当前统计的是各年级的全部学生数,而非符合条件的学生数,求技术帮助。

JSON数据

{
  "students": [
    {
      "fullName": "Student 1",
      "standard": 10,
      "rollNumber": "1R",
      "house": "Red",
      "marks": {
        "maths": 90,
        "english": 90,
        "science": 80,
        "history": 90
      },
      "totalMarks": 350,
      "sports": [
        {
          "sportName": "karate",
          "status": "purple-belt"
        },
        {
          "sportName": "swimming",
          "status": "swimmer"
        },
        {
          "sportName": "karate",
          "status": "green-belt"
        }
      ],
      "hobbies": [
        "programming",
        "reading"
      ]
    },
    {
      "fullName": "Student 2",
      "standard": 10,
      "rollNumber": "2R",
      "house": "Blue",
      "marks": {
        "maths": 90,
        "english": 90,
        "science": 90,
        "history": 90
      },
      "totalMarks": 360,
      "sports": [
        {
          "sportName": "cricket",
          "status": "all-rounder"
        }
      ],
      "hobbies": [
        "gaming"
      ]
    }
  ]
}

现有代码

Map<Integer, Long> map10 = reportCard.getStudents().stream().collect(Collectors.groupingBy(Student::getStandard, Collectors.mapping(student -> student.getHobbies().stream().filter(hobby -> hobby.equalsIgnoreCase("programming")),Collectors.counting())));
        System.out.println("map10");
        map10.forEach((key, value) -> System.out.println(key + "-" + value));

问题原因

你的代码里,Collectors.mapping只是把每个学生转换成了一个过滤爱好的Stream对象,但Collectors.counting()不会处理这个Stream,它只会统计当前分组下的学生总数——相当于过滤逻辑完全没生效,自然得到的是各年级的全部学生数。

解决方案

这里提供两种可行的实现方式,你可以根据需求选择:

方式一:先筛选再分组(仅保留有符合条件学生的年级)

先过滤出所有爱好包含programming的学生,再按年级分组计数。如果某个年级没有符合条件的学生,不会出现在结果Map中。

Map<Integer, Long> map10 = reportCard.getStudents().stream()
    // 筛选出爱好包含programming的学生(忽略大小写)
    .filter(student -> student.getHobbies().stream()
        .anyMatch(hobby -> hobby.equalsIgnoreCase("programming")))
    // 按年级分组并统计数量
    .collect(Collectors.groupingBy(Student::getStandard, Collectors.counting()));

System.out.println("map10");
map10.forEach((key, value) -> System.out.println(key + "-" + value));

方式二:分组后再筛选(保留所有年级,无符合条件则计数为0)

使用Collectors.filtering在分组后对每个年级的学生列表进行筛选统计,这样即使某个年级没有符合条件的学生,也会在结果Map中保留该年级,计数为0。

Map<Integer, Long> map10 = reportCard.getStudents().stream()
    .collect(Collectors.groupingBy(Student::getStandard, 
        // 对每个年级的学生,统计符合爱好条件的人数
        Collectors.filtering(student -> student.getHobbies().stream()
            .anyMatch(hobby -> hobby.equalsIgnoreCase("programming")), 
            Collectors.counting())));

System.out.println("map10");
map10.forEach((key, value) -> System.out.println(key + "-" + value));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 21:30:22