本文目录导读:

在Java中,使用Stream进行数据统计是一个非常常见的场景,尤其是在处理集合(List、Set等)或数组时,Stream API提供了强大的函数式编程能力,可以让你用简洁、优雅的代码完成分组、求和、求平均值、最大最小值等统计操作。
下面我将通过几个典型的Java案例,演示如何使用Stream进行数据统计。
案例1:对基础类型列表进行简单统计
假设有一个整数列表,需要计算总和、数量、平均值、最大值和最小值。
import java.util.*;
import java.util.stream.*;
public class BasicStats {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(10, 20, 30, 40, 50);
// 使用 IntStream 的 summaryStatistics() 方法
IntSummaryStatistics stats = numbers.stream()
.mapToInt(Integer::intValue) // 转为 IntStream
.summaryStatistics();
System.out.println("数量: " + stats.getCount());
System.out.println("总和: " + stats.getSum());
System.out.println("平均值: " + stats.getAverage());
System.out.println("最大值: " + stats.getMax());
System.out.println("最小值: " + stats.getMin());
}
}
输出:
数量: 5
总和: 150
平均值: 30.0
最大值: 50
最小值: 10
案例2:统计自定义对象(如员工工资)
假设有一个Employee类,需要统计所有员工的工资总和、平均工资、最高工资和最低工资。
import java.util.*;
import java.util.stream.*;
class Employee {
private String name;
private double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public double getSalary() { return salary; }
public String getName() { return name; }
}
public class EmployeeStats {
public static void main(String[] args) {
List<Employee> employees = Arrays.asList(
new Employee("Alice", 5000),
new Employee("Bob", 6000),
new Employee("Charlie", 4500),
new Employee("David", 7000)
);
// 统计所有员工的工资
DoubleSummaryStatistics salaryStats = employees.stream()
.mapToDouble(Employee::getSalary) // 转为 DoubleStream
.summaryStatistics();
System.out.println("员工总数: " + salaryStats.getCount());
System.out.println("工资总和: " + salaryStats.getSum());
System.out.println("平均工资: " + salaryStats.getAverage());
System.out.println("最高工资: " + salaryStats.getMax());
System.out.println("最低工资: " + salaryStats.getMin());
}
}
输出:
员工总数: 4
工资总和: 22500.0
平均工资: 5625.0
最高工资: 7000.0
最低工资: 4500.0
案例3:按部门分组并统计每个部门的工资情况
这是实际业务中非常常见的需求,使用Collectors.groupingBy()配合Collectors.summarizingDouble()可以实现分组统计。
import java.util.*;
import java.util.stream.*;
class Employee2 {
private String name;
private String department;
private double salary;
public Employee2(String name, String department, double salary) {
this.name = name;
this.department = department;
this.salary = salary;
}
public String getDepartment() { return department; }
public double getSalary() { return salary; }
public String getName() { return name; }
}
public class GroupedStats {
public static void main(String[] args) {
List<Employee2> employees = Arrays.asList(
new Employee2("Alice", "IT", 5000),
new Employee2("Bob", "HR", 4000),
new Employee2("Charlie", "IT", 6000),
new Employee2("David", "HR", 4500),
new Employee2("Eve", "IT", 5500)
);
// 按部门分组,统计每个部门的工资信息
Map<String, DoubleSummaryStatistics> deptStats = employees.stream()
.collect(Collectors.groupingBy(
Employee2::getDepartment,
Collectors.summarizingDouble(Employee2::getSalary)
));
// 输出每个部门的统计结果
deptStats.forEach((dept, stats) -> {
System.out.println("部门: " + dept);
System.out.println(" 人数: " + stats.getCount());
System.out.println(" 总工资: " + stats.getSum());
System.out.println(" 平均工资: " + stats.getAverage());
System.out.println(" 最高工资: " + stats.getMax());
System.out.println(" 最低工资: " + stats.getMin());
System.out.println();
});
}
}
输出:
部门: HR
人数: 2
总工资: 8500.0
平均工资: 4250.0
最高工资: 4500.0
最低工资: 4000.0
部门: IT
人数: 3
总工资: 16500.0
平均工资: 5500.0
最高工资: 6000.0
最低工资: 5000.0
-
选择合适的Stream类型:
IntStream:处理int数据。LongStream:处理long数据。DoubleStream:处理double数据。Stream<T>:处理对象流,但需要通过mapToInt()、mapToLong()或mapToDouble()转换。
-
使用
summaryStatistics()方法:- 这是获取一次性统计结果(计数、总和、平均值、最大、最小)的最便捷方法。
- 分别对应:
IntSummaryStatistics、LongSummaryStatistics、DoubleSummaryStatistics。
-
分组统计(核心):
- 使用
Collectors.groupingBy(keyExtractor, downstreamCollector)。 downstreamCollector可以是Collectors.summarizingDouble()、Collectors.counting()、Collectors.averagingDouble()、Collectors.summingDouble()等。
- 使用
-
高级用法:
- 自定义统计:除了内置的统计类,你也可以使用
reduce()方法进行复杂的自定义聚合操作。 - 多条件统计:可以结合
filter()、sorted()、limit()等中间操作先筛选或排序,再进行统计。
- 自定义统计:除了内置的统计类,你也可以使用
掌握这些Stream统计技巧,可以让你用更少的代码完成更复杂的统计分析,并提升代码的可读性,如果你有更具体的需求(如统计中位数、众数等),可以结合Collectors.toList()然后手动计算,或者使用第三方库(如Apache Commons Math)。