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
相关产品推荐
相关产品推荐

