
在日常数据处理中,我们经常会遇到需要统计列表中特定类别元素出现频率的场景。例如,在一个包含家庭成员信息的列表中,我们可能需要统计不同类型的家庭成员(如兄弟姐妹、子女、配偶)各自有多少人。原始数据可能以 list<map<string, string>> 的形式存在,其中每个 map 代表一个成员的详细信息,例如:
| Add_Family_Member | Full_Name | Date_Of_Birth | Gender | | Sibling | Sibling name | 12-12-1990 | Male | | Sibling | Sibling name2 | 12-12-1990 | Male | | Sibling | Sibling name2 | 12-12-1990 | Male | | Child | Child name | 12-12-2010 | Male | | Child | Child name2 | 12-12-2000 | Female | | Spouse | Spouse name | 12-12-1990 | Male |
我们的目标是高效地统计出 "Sibling" 有 3 个,"Child" 有 2 个,"Spouse" 有 1 个。
虽然 List<Map<String, String>> 可以存储这类数据,但它在处理时存在一些局限性,例如缺乏类型安全,在访问数据时需要通过字符串键来获取,容易出错且代码可读性差。对于结构化的数据,更推荐的做法是定义一个POJO(Plain Old Java Object)类来封装数据。这不仅提供了编译时类型检查,还能使代码更清晰、更易于维护。
以下是 FamilyMember POJO 类的定义:
import java.time.LocalDate; // Java 8日期API
public class FamilyMember {
private String memberType;
private String fullName;
private LocalDate dateOfBirth;
private String gender;
public FamilyMember(String memberType, String fullName,
LocalDate dateOfBirth, String gender) {
this.memberType = memberType;
this.fullName = fullName;
this.dateOfBirth = dateOfBirth;
this.gender = gender;
}
// Getters
public String getMemberType() {
return memberType;
}
public String getFullName() {
return fullName;
}
public LocalDate getDateOfBirth() {
return dateOfBirth;
}
public String getGender() {
return gender;
}
// Setters (可选,根据业务需求添加)
public void setMemberType(String memberType) {
this.memberType = memberType;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public void setDateOfBirth(LocalDate dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public void setGender(String gender) {
this.gender = gender;
}
}Java 8 引入的 Stream API 提供了强大且富有表现力的数据处理能力。结合 Collectors.groupingBy() 和 Collectors.counting(),我们可以非常简洁地实现按类型计数的需求。
立即学习“Java免费学习笔记(深入)”;
下面是具体的实现代码,展示了如何使用 FamilyMember POJO 和 Stream API 进行统计:
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class FamilyMemberCounter {
public static void main(String[] args) {
// 1. 创建FamilyMember对象列表作为示例数据
List<FamilyMember> listOfFamilyMember = Arrays.asList(
new FamilyMember("Sibling", "Sibling name", LocalDate.of(1990, 12, 12), "Male"),
new FamilyMember("Sibling", "Sibling name2", LocalDate.of(1990, 12, 12), "Male"),
new FamilyMember("Sibling", "Sibling name3", LocalDate.of(1990, 12, 12), "Male"),
new FamilyMember("Child", "Child name", LocalDate.of(2010, 12, 12), "Male"),
new FamilyMember("Child", "Child name2", LocalDate.of(2000, 12, 12), "Female"),
new FamilyMember("Spouse", "Spouse name", LocalDate.of(1990, 12, 12), "Male")
);
// 2. 使用Stream API进行分组和计数
// 将列表转换为流,然后使用Collectors.groupingBy按memberType分组,并用Collectors.counting统计每个组的数量
Map<String, Long> countMembers = listOfFamilyMember.stream()
.collect(Collectors.groupingBy(FamilyMember::getMemberType, // 分组依据:FamilyMember的memberType属性
Collectors.counting())); // 对每个分组内的元素进行计数
// 3. 打印结果
System.out.println(countMembers);
}
}代码解析:
输出结果:
{Spouse=1, Sibling=3, Child=2}这个输出清晰地展示了每种家庭成员类型的数量,与我们的预期完全一致。
// 假设 inputList 是 List<Map<String, String>>
Map<String, Long> countMapFromRaw = inputList.stream()
.collect(Collectors.groupingBy(map -> map.get("Add_Family_Member"),
Collectors.counting()));但这种方式不如使用POJO类型安全和优雅,因为字符串键容易拼写错误且编译时无法检查。
本文详细阐述了如何利用Java 8 Stream API中的 Collectors.groupingBy() 和 Collectors.counting() 功能,高效地统计集合中特定类型元素的出现次数。通过将原始的 List<Map<String, String>> 结构优化为POJO类,我们不仅提升了代码的健壮性和可读性,还展示了流式操作在数据聚合方面的强大能力。掌握这些技术,可以显著提高Java应用程序中数据处理的效率和代码质量。
以上就是Java 8 Stream:高效统计集合中指定类型元素的出现次数的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号