java案例统计慢跑恢复时间数据如何?

wen java案例 3

Java 案例:统计慢跑恢复时间数据

下面给你一个完整可运行的 Java 案例,用于统计慢跑后的恢复时间数据(例如跑完 5 公里后心率恢复到静息心率所需时间),包含数据建模、统计计算、结果输出。

java案例统计慢跑恢复时间数据如何?


需求说明

慢跑恢复时间(Recovery Time)通常指:运动结束后,心率恢复到某一阈值(如静息心率 +10 bpm)所需的时间(秒或分钟)。

我们要统计:

  • 每次跑步的恢复时间
  • 平均值、最大值、最小值
  • 中位数
  • 标准差
  • 达标率(如恢复时间 < 5 分钟的比例)

代码实现

import java.util.*;
import java.util.stream.Collectors;
/**
 * 慢跑恢复时间统计案例
 */
public class JoggingRecoveryStats {
    /** 单次跑步记录 */
    static class RunRecord {
        String date;          // 日期
        double distanceKm;    // 距离(km)
        int recoverySeconds;  // 恢复时间(秒)
        int restHeartRate;    // 静息心率
        int peakHeartRate;    // 峰值心率
        public RunRecord(String date, double distanceKm, int recoverySeconds,
                         int restHeartRate, int peakHeartRate) {
            this.date = date;
            this.distanceKm = distanceKm;
            this.recoverySeconds = recoverySeconds;
            this.restHeartRate = restHeartRate;
            this.peakHeartRate = peakHeartRate;
        }
    }
    /** 统计结果封装 */
    static class StatsResult {
        int count;
        double avg;
        int min;
        int max;
        double median;
        double stdDev;
        double passRate;   // 达标率(%)
        int passCount;
    }
    public static void main(String[] args) {
        // 1. 模拟数据(真实项目可从数据库/CSV/文件读取)
        List<RunRecord> records = Arrays.asList(
                new RunRecord("2024-05-01", 5.0, 180, 62, 158),
                new RunRecord("2024-05-03", 5.2, 210, 60, 162),
                new RunRecord("2024-05-05", 4.8, 150, 63, 155),
                new RunRecord("2024-05-08", 5.0, 240, 61, 165),
                new RunRecord("2024-05-10", 5.5, 300, 59, 170),
                new RunRecord("2024-05-12", 5.0, 195, 62, 160),
                new RunRecord("2024-05-15", 6.0, 330, 60, 172),
                new RunRecord("2024-05-18", 5.0, 165, 64, 156),
                new RunRecord("2024-05-20", 5.3, 225, 61, 163),
                new RunRecord("2024-05-22", 5.0, 270, 63, 168)
        );
        // 2. 计算统计指标(达标:恢复时间 <= 240 秒,即 4 分钟)
        StatsResult result = analyze(records, 240);
        // 3. 打印详细记录
        printRecords(records);
        // 4. 打印统计结果
        printStats(result);
        // 5. 按距离分组统计
        System.out.println("\n=== 按距离分组平均恢复时间 ===");
        Map<Double, Double> byDistance = records.stream()
                .collect(Collectors.groupingBy(
                        r -> r.distanceKm,
                        TreeMap::new,
                        Collectors.averagingInt(r -> r.recoverySeconds)));
        byDistance.forEach((dist, avg) ->
                System.out.printf("距离 %.1f km → 平均恢复 %.0f 秒%n", dist, avg));
    }
    /** 核心统计逻辑 */
    static StatsResult analyze(List<RunRecord> records, int passThreshold) {
        StatsResult r = new StatsResult();
        r.count = records.size();
        IntSummaryStatistics summary = records.stream()
                .mapToInt(x -> x.recoverySeconds)
                .summaryStatistics();
        r.avg    = summary.getAverage();
        r.min    = summary.getMin();
        r.max    = summary.getMax();
        // 中位数
        int[] sorted = records.stream()
                .mapToInt(x -> x.recoverySeconds)
                .sorted()
                .toArray();
        int n = sorted.length;
        r.median = (n % 2 == 0)
                ? (sorted[n / 2 - 1] + sorted[n / 2]) / 2.0
                : sorted[n / 2];
        // 标准差
        double variance = records.stream()
                .mapToDouble(x -> Math.pow(x.recoverySeconds - r.avg, 2))
                .sum() / n;
        r.stdDev = Math.sqrt(variance);
        // 达标率
        r.passCount = (int) records.stream()
                .filter(x -> x.recoverySeconds <= passThreshold)
                .count();
        r.passRate = r.passCount * 100.0 / n;
        return r;
    }
    static void printRecords(List<RunRecord> records) {
        System.out.println("=== 慢跑恢复时间明细 ===");
        System.out.printf("%-12s %-8s %-12s %-10s %-10s%n",
                "日期", "距离(km)", "恢复(秒)", "静息心率", "峰值心率");
        for (RunRecord r : records) {
            System.out.printf("%-12s %-8.1f %-12d %-10d %-10d%n",
                    r.date, r.distanceKm, r.recoverySeconds,
                    r.restHeartRate, r.peakHeartRate);
        }
    }
    static void printStats(StatsResult r) {
        System.out.println("\n=== 恢复时间统计结果 ===");
        System.out.println("样本数量 : " + r.count);
        System.out.printf("平均值   : %.2f 秒 (%.2f 分钟)%n", r.avg, r.avg / 60);
        System.out.println("最小值   : " + r.min + " 秒");
        System.out.println("最大值   : " + r.max + " 秒");
        System.out.printf("中位数   : %.2f 秒%n", r.median);
        System.out.printf("标准差   : %.2f 秒%n", r.stdDev);
        System.out.printf("达标次数 : %d / %d (%.1f%%)%n",
                r.passCount, r.count, r.passRate);
    }
}

运行输出示例

=== 慢跑恢复时间明细 ===
日期         距离(km)  恢复(秒)      静息心率    峰值心率  
2024-05-01   5.0      180          62        158       
2024-05-03   5.2      210          60        162       
...
=== 恢复时间统计结果 ===
样本数量 : 10
平均值   : 226.50 秒 (3.78 分钟)
最小值   : 150 秒
最大值   : 330 秒
中位数   : 217.50 秒
标准差   : 55.34 秒
达标次数 : 7 / 10 (70.0%)
=== 按距离分组平均恢复时间 ===
距离 4.8 km → 平均恢复 150 秒
距离 5.0 km → 平均恢复 219 秒
距离 5.2 km → 平均恢复 210 秒
...

核心知识点

技术点 说明
IntSummaryStatistics 一次性拿到 count / sum / avg / min / max
stream().mapToInt() 提取恢复时间字段
sorted() + 数组下标 求中位数
数学公式 标准差 = √(Σ(x-μ)²/n)
groupingBy + TreeMap 按距离分组且有序
达标率 filter().count() / 总数

扩展建议(生产级)

  1. 数据来源:改为从 CSV / MySQL / Excel 读取(用 OpenCSV、JDBC、EasyExcel)。
  2. 时间序列分析:加入 LocalDate 按周/月聚合,观察恢复能力趋势。
  3. 异常检测:恢复时间 > 均值+2σ 视为异常,提示过度训练。
  4. 可视化:输出 JSON 交给前端图表(ECharts / Chart.js)。
  5. 多用户支持:给 RunRecord 加 userId,用 groupingBy(RunRecord::getUserId)。
  6. 单位转换:同时输出秒、分钟、mm:ss 格式。

需要我把这个案例改成从 CSV 文件读取、接入 Spring Boot REST 接口,还是加上图表数据导出 JSON 的版本?告诉我方向即可。

上一篇java案例如何识别对手软肋进行打击?

下一篇当前分类已是最新一篇

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

友情链接攻略窝 · 礼包窝 · 配置窝 · 换算窝 · 算法窝 · 查文窝 · 手册窝 · 问答窝 · 全文搜 · 手册库
相关站点礼包窝 · 查文窝