使用Java Lambda表达式进行List分组及多个属性统计

在Java 8及更高版本中,Lambda表达式和Stream API的引入,使得数据的处理变得更加简洁和高效。特别是在对List进行分组和统计操作时,我们可以非常方便地实现相关功能。本文将探索如何使用Java的Lambda和Stream API对一个包含多个属性的对象集合进行分组并进行统计。

例子背景

假设我们有一个Person类,它包含了一些属性,如姓名、年龄和城市。我们的目标是统计每个城市中不同年龄段的人数。

public class Person {
    private String name;
    private int age;
    private String city;

    // 构造函数和getter/setter省略
}

创建一个列表

首先,我们需要创建一个List<Person>,其中包含多个Person对象。

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Person> people = new ArrayList<>();
        
        people.add(new Person("Alice", 30, "New York"));
        people.add(new Person("Bob", 25, "New York"));
        people.add(new Person("Charlie", 35, "Los Angeles"));
        people.add(new Person("David", 25, "Los Angeles"));
        people.add(new Person("Eve", 30, "New York"));
        people.add(new Person("Frank", 35, "Chicago"));
        
        // 进行分组统计
    }
}

使用Stream API进行分组统计

为了对这些Person对象进行统计,我们可以使用Collectors.groupingBy方法。我们可以通过groupingBy方法首先根据城市分组,然后统计不同年龄段的人数。

import java.util.Map;
import java.util.stream.Collectors;

Map<String, Map<Integer, Long>> groupedByCityAndAge = people.stream()
    .collect(Collectors.groupingBy(
        Person::getCity, // 按城市分组
        Collectors.groupingBy(
            Person::getAge, // 按年龄分组
            Collectors.counting() // 进行计数
        )
    ));

在上面的代码中,groupingBy方法创建了一个嵌套的Map,外层的Map以城市为键,内层的Map以年龄为键,并且值为该年龄对应的人数。使用Collectors.counting()进行计数。

输出结果

接下来,我们可以将结果输出,来观察每个城市中不同年龄段的人数。

groupedByCityAndAge.forEach((city, ageCounts) -> {
    System.out.println("City: " + city);
    ageCounts.forEach((age, count) -> {
        System.out.println("  Age: " + age + ", Count: " + count);
    });
});

完整代码示例

将以上代码整合后,我们的完整示例代码如下:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Person> people = new ArrayList<>();
        
        people.add(new Person("Alice", 30, "New York"));
        people.add(new Person("Bob", 25, "New York"));
        people.add(new Person("Charlie", 35, "Los Angeles"));
        people.add(new Person("David", 25, "Los Angeles"));
        people.add(new Person("Eve", 30, "New York"));
        people.add(new Person("Frank", 35, "Chicago"));

        Map<String, Map<Integer, Long>> groupedByCityAndAge = people.stream()
            .collect(Collectors.groupingBy(
                Person::getCity,
                Collectors.groupingBy(
                    Person::getAge,
                    Collectors.counting()
                )
            ));
        
        groupedByCityAndAge.forEach((city, ageCounts) -> {
            System.out.println("City: " + city);
            ageCounts.forEach((age, count) -> {
                System.out.println("  Age: " + age + ", Count: " + count);
            });
        });
    }
}

旅行图示

在此示例的过程中,我们的思路可以通过以下旅行图示表示:

journey
    title 使用Java Lambda进行List分组统计
    section 创建数据
      创建Person对象: 5: Person
      添加到列表: 5: User
    section 分组统计
      使用Stream API分组按城市: 5: Stream
      进一步分组按年龄: 5: Stream
    section 输出结果
      打印每个城市的年龄统计: 5: Output

结论

通过使用Java的Lambda表达式和Stream API,我们能够高效地对集合数据进行分组和统计操作。无论是统计数据分析、报表生成还是第三方服务的数据整合,这种方式都使开发者的工作变得更加轻松且高效。掌握这些技能,将有助于在日常开发工作中提高工作效率。希望本文对你在Java开发中的数据处理有所帮助!