Java案例怎么用Stream统计数据?

wen java案例 13

本文目录导读:

Java案例怎么用Stream统计数据?

  1. 案例1:对基础类型列表进行简单统计
  2. 案例2:统计自定义对象(如员工工资)
  3. 案例3:按部门分组并统计每个部门的工资情况

在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
  1. 选择合适的Stream类型

    • IntStream:处理int数据。
    • LongStream:处理long数据。
    • DoubleStream:处理double数据。
    • Stream<T>:处理对象流,但需要通过mapToInt()mapToLong()mapToDouble()转换。
  2. 使用summaryStatistics()方法

    • 这是获取一次性统计结果(计数、总和、平均值、最大、最小)的最便捷方法。
    • 分别对应:IntSummaryStatisticsLongSummaryStatisticsDoubleSummaryStatistics
  3. 分组统计(核心)

    • 使用Collectors.groupingBy(keyExtractor, downstreamCollector)
    • downstreamCollector可以是Collectors.summarizingDouble()Collectors.counting()Collectors.averagingDouble()Collectors.summingDouble()等。
  4. 高级用法

    • 自定义统计:除了内置的统计类,你也可以使用reduce()方法进行复杂的自定义聚合操作。
    • 多条件统计:可以结合filter()sorted()limit()等中间操作先筛选或排序,再进行统计。

掌握这些Stream统计技巧,可以让你用更少的代码完成更复杂的统计分析,并提升代码的可读性,如果你有更具体的需求(如统计中位数、众数等),可以结合Collectors.toList()然后手动计算,或者使用第三方库(如Apache Commons Math)。

抱歉,评论功能暂时关闭!