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类有三个属性:nameageclassroom。我们根据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.summingIntCollectors.averagingIntCollectors.maxByCollectors.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'}]}

可以看到,每个班级中的学生年龄的总和、平均值、最大值和最小值都被