Java 8中的GroupBy分组统计排序
在Java 8中,GroupBy
是一种非常强大的操作,它可以将集合中的元素按照指定的条件进行分组,并对每个组进行统计和排序。这个功能对于数据分析和报告生成非常有用。
GroupBy的基本用法
在Java 8中,可以使用Collectors.groupingBy
方法来进行分组操作。这个方法可以接受一个Function
类型的参数,用于指定根据哪个属性或条件进行分组。下面是一个示例,演示如何将一个学生集合按照班级进行分组:
List<Student> students = Arrays.asList(
new Student("Alice", 10, "Class A"),
new Student("Bob", 12, "Class B"),
new Student("Charlie", 11, "Class A"),
new Student("David", 11, "Class B")
);
Map<String, List<Student>> groupedStudents = students.stream()
.collect(Collectors.groupingBy(Student::getClassroom));
System.out.println(groupedStudents);
这个示例中,Student
类有三个属性:name
、age
和classroom
。我们根据classroom
属性对学生进行分组,并将结果存储在一个Map
对象中。输出结果如下:
{Class A=[Student{name='Alice', age=10, classroom='Class A'}, Student{name='Charlie', age=11, classroom='Class A'}], Class B=[Student{name='Bob', age=12, classroom='Class B'}, Student{name='David', age=11, classroom='Class B'}]}
可以看到,学生被正确地按照班级进行了分组。
分组后的统计和排序
除了分组,Java 8还提供了一些用于对每个组进行统计和排序的操作。
统计每个组内的元素数量
我们可以使用Collectors.counting
方法来统计每个组内的元素数量。下面是一个示例,演示如何统计每个班级中学生的数量:
Map<String, Long> studentCountByClassroom = students.stream()
.collect(Collectors.groupingBy(Student::getClassroom, Collectors.counting()));
System.out.println(studentCountByClassroom);
输出结果如下:
{Class A=2, Class B=2}
可以看到,每个班级中的学生数量被正确地统计出来了。
求每个组内的元素属性的和、平均值、最大值和最小值
除了统计数量,我们还可以使用Collectors.summingInt
、Collectors.averagingInt
、Collectors.maxBy
和Collectors.minBy
等方法来进行求和、平均值、最大值和最小值的统计。
下面是一个示例,演示如何统计每个班级中学生的年龄总和、平均年龄、最大年龄和最小年龄:
Map<String, Integer> totalAgeByClassroom = students.stream()
.collect(Collectors.groupingBy(Student::getClassroom, Collectors.summingInt(Student::getAge)));
Map<String, Double> averageAgeByClassroom = students.stream()
.collect(Collectors.groupingBy(Student::getClassroom, Collectors.averagingInt(Student::getAge)));
Map<String, Optional<Student>> maxAgeByClassroom = students.stream()
.collect(Collectors.groupingBy(Student::getClassroom, Collectors.maxBy(Comparator.comparingInt(Student::getAge))));
Map<String, Optional<Student>> minAgeByClassroom = students.stream()
.collect(Collectors.groupingBy(Student::getClassroom, Collectors.minBy(Comparator.comparingInt(Student::getAge))));
System.out.println(totalAgeByClassroom);
System.out.println(averageAgeByClassroom);
System.out.println(maxAgeByClassroom);
System.out.println(minAgeByClassroom);
输出结果如下:
{Class A=21, Class B=23}
{Class A=10.5, Class B=11.5}
{Class A=Optional[Student{name='Charlie', age=11, classroom='Class A'}], Class B=Optional[Student{name='Bob', age=12, classroom='Class B'}]}
{Class A=Optional[Student{name='Alice', age=10, classroom='Class A'}], Class B=Optional[Student{name='David', age=11, classroom='Class B'}]}
可以看到,每个班级中的学生年龄的总和、平均值、最大值和最小值都被