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

wen java案例 1

本文目录导读:

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

  1. 完整实现代码
  2. 运行示例
  3. 功能说明
  4. 扩展建议

我来为您提供一个完整的Java案例,用于统计慢跑恢复时间数据,这个案例将包含数据收集、统计分析和可视化展示的功能。

完整实现代码

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
 * 慢跑恢复时间统计分析系统
 */
public class RunningRecoveryStats {
    // 数据模型:慢跑记录
    static class RunningRecord {
        private LocalDateTime runTime;      // 跑步时间
        private double distanceKm;         // 距离(公里)
        private int durationMinutes;       // 时长(分钟)
        private int avgHeartRate;          // 平均心率
        private int recoveryHours;         // 恢复时间(小时)
        private String difficultyLevel;    // 难度等级
        public RunningRecord(LocalDateTime runTime, double distanceKm, 
                           int durationMinutes, int avgHeartRate) {
            this.runTime = runTime;
            this.distanceKm = distanceKm;
            this.durationMinutes = durationMinutes;
            this.avgHeartRate = avgHeartRate;
            // 根据心率计算恢复时间(简单算法)
            this.recoveryHours = calculateRecoveryTime();
            this.difficultyLevel = determineDifficulty();
        }
        // 计算恢复时间(基于心率储备的简化算法)
        private int calculateRecoveryTime() {
            if (avgHeartRate < 120) return 12;
            else if (avgHeartRate < 140) return 24;
            else if (avgHeartRate < 160) return 36;
            else if (avgHeartRate < 180) return 48;
            else return 72;
        }
        // 判断难度等级
        private String determineDifficulty() {
            int pace = durationMinutes * 60 / (int)(distanceKm * 1000) * 1000 / 60;
            if (pace < 5) return "高强度";
            else if (pace < 6) return "中高强度";
            else if (pace < 7) return "中等强度";
            else return "低强度";
        }
        // Getters
        public LocalDateTime getRunTime() { return runTime; }
        public double getDistanceKm() { return distanceKm; }
        public int getDurationMinutes() { return durationMinutes; }
        public int getAvgHeartRate() { return avgHeartRate; }
        public int getRecoveryHours() { return recoveryHours; }
        public String getDifficultyLevel() { return difficultyLevel; }
        @Override
        public String toString() {
            return String.format("跑步时间: %s, 距离: %.1fkm, 时长: %d分钟, " +
                               "平均心率: %d, 恢复时间: %d小时, 难度: %s",
                runTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")),
                distanceKm, durationMinutes, avgHeartRate, recoveryHours, difficultyLevel);
        }
    }
    // 统计分析类
    static class RecoveryAnalyzer {
        private List<RunningRecord> records;
        public RecoveryAnalyzer(List<RunningRecord> records) {
            this.records = records;
        }
        // 基本统计信息
        public Map<String, Object> getBasicStats() {
            Map<String, Object> stats = new HashMap<>();
            // 总记录数
            stats.put("totalRecords", records.size());
            // 平均恢复时间
            double avgRecovery = records.stream()
                .mapToInt(RunningRecord::getRecoveryHours)
                .average()
                .orElse(0);
            stats.put("avgRecoveryHours", avgRecovery);
            // 最长恢复时间
            int maxRecovery = records.stream()
                .mapToInt(RunningRecord::getRecoveryHours)
                .max()
                .orElse(0);
            stats.put("maxRecoveryHours", maxRecovery);
            // 最短恢复时间
            int minRecovery = records.stream()
                .mapToInt(RunningRecord::getRecoveryHours)
                .min()
                .orElse(0);
            stats.put("minRecoveryHours", minRecovery);
            // 总里程
            double totalDistance = records.stream()
                .mapToDouble(RunningRecord::getDistanceKm)
                .sum();
            stats.put("totalDistance", totalDistance);
            // 平均配速(分钟/公里)
            double avgPace = records.stream()
                .mapToDouble(r -> (double)r.getDurationMinutes() / r.getDistanceKm())
                .average()
                .orElse(0);
            stats.put("avgPace", avgPace);
            return stats;
        }
        // 按月份统计平均恢复时间
        public Map<String, Double> getMonthlyAvgRecovery() {
            return records.stream()
                .collect(Collectors.groupingBy(
                    r -> r.getRunTime().format(DateTimeFormatter.ofPattern("yyyy-MM")),
                    Collectors.averagingInt(RunningRecord::getRecoveryHours)
                ));
        }
        // 按难度等级统计
        public Map<String, List<RunningRecord>> groupByDifficulty() {
            return records.stream()
                .collect(Collectors.groupingBy(RunningRecord::getDifficultyLevel));
        }
        // 恢复时间分布(按区间)
        public Map<String, Long> getRecoveryDistribution() {
            return records.stream()
                .collect(Collectors.groupingBy(r -> {
                    int hours = r.getRecoveryHours();
                    if (hours <= 12) return "≤12小时";
                    else if (hours <= 24) return "13-24小时";
                    else if (hours <= 36) return "25-36小时";
                    else if (hours <= 48) return "37-48小时";
                    else return ">48小时";
                }, Collectors.counting()));
        }
        // 趋势分析(最近N次恢复时间变化)
        public List<Integer> getRecentTrend(int n) {
            return records.stream()
                .sorted((r1, r2) -> r2.getRunTime().compareTo(r1.getRunTime()))
                .limit(n)
                .map(RunningRecord::getRecoveryHours)
                .collect(Collectors.toList());
        }
        // 预测下一次恢复时间(简单移动平均)
        public double predictNextRecovery() {
            if (records.size() < 3) {
                return records.stream()
                    .mapToInt(RunningRecord::getRecoveryHours)
                    .average()
                    .orElse(24);
            }
            // 使用最近3次的加权平均
            List<RunningRecord> sorted = records.stream()
                .sorted((r1, r2) -> r2.getRunTime().compareTo(r1.getRunTime()))
                .limit(3)
                .collect(Collectors.toList());
            double weight1 = 0.5, weight2 = 0.3, weight3 = 0.2;
            return sorted.get(0).getRecoveryHours() * weight1 +
                   sorted.get(1).getRecoveryHours() * weight2 +
                   sorted.get(2).getRecoveryHours() * weight3;
        }
    }
    // 可视化输出类
    static class StatsVisualizer {
        // 打印柱状图(恢复时间分布)
        public static void printRecoveryBarChart(Map<String, Long> distribution) {
            System.out.println("\n=== 恢复时间分布图 ===");
            long maxCount = distribution.values().stream()
                .max(Long::compare).orElse(1L);
            distribution.entrySet().stream()
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                .forEach(entry -> {
                    String bar = "#".repeat((int)(entry.getValue() * 40 / maxCount));
                    System.out.printf("%-12s | %s %d次%n", 
                        entry.getKey(), bar, entry.getValue());
                });
        }
        // 打印月度趋势线
        public static void printMonthlyTrend(Map<String, Double> monthlyData) {
            System.out.println("\n=== 月度平均恢复时间趋势 ===");
            double maxValue = monthlyData.values().stream()
                .max(Double::compare).orElse(1.0);
            monthlyData.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .forEach(entry -> {
                    int barLength = (int)(entry.getValue() * 30 / maxValue);
                    String bar = "━".repeat(barLength);
                    System.out.printf("%s | %s %.1f小时%n", 
                        entry.getKey(), bar, entry.getValue());
                });
        }
        // 打印统计摘要
        public static void printSummary(Map<String, Object> stats) {
            System.out.println("\n=== 跑步统计摘要 ===");
            stats.forEach((key, value) -> {
                switch(key) {
                    case "totalRecords":
                        System.out.printf("%-20s: %d次%n", "总跑步次数", value);
                        break;
                    case "avgRecoveryHours":
                        System.out.printf("%-20s: %.1f小时%n", "平均恢复时间", value);
                        break;
                    case "maxRecoveryHours":
                        System.out.printf("%-20s: %d小时%n", "最长恢复时间", value);
                        break;
                    case "minRecoveryHours":
                        System.out.printf("%-20s: %d小时%n", "最短恢复时间", value);
                        break;
                    case "totalDistance":
                        System.out.printf("%-20s: %.1f公里%n", "总里程", value);
                        break;
                    case "avgPace":
                        System.out.printf("%-20s: %.2f分钟/公里%n", "平均配速", value);
                        break;
                    default:
                        System.out.printf("%-20s: %s%n", key, value);
                }
            });
        }
    }
    // 测试主方法
    public static void main(String[] args) {
        // 生成模拟数据
        List<RunningRecord> records = generateMockData();
        // 创建分析器
        RecoveryAnalyzer analyzer = new RecoveryAnalyzer(records);
        // 打印所有跑步记录
        System.out.println("=== 慢跑记录列表 ===");
        records.forEach(System.out::println);
        // 基本统计
        Map<String, Object> basicStats = analyzer.getBasicStats();
        StatsVisualizer.printSummary(basicStats);
        // 月度统计
        Map<String, Double> monthlyStats = analyzer.getMonthlyAvgRecovery();
        StatsVisualizer.printMonthlyTrend(monthlyStats);
        // 难度分组
        Map<String, List<RunningRecord>> difficultyGroups = analyzer.groupByDifficulty();
        System.out.println("\n=== 难度等级分组 ===");
        difficultyGroups.forEach((level, list) -> {
            System.out.printf("%s: %d次跑步%n", level, list.size());
        });
        // 恢复时间分布
        Map<String, Long> distribution = analyzer.getRecoveryDistribution();
        StatsVisualizer.printRecoveryBarChart(distribution);
        // 趋势分析
        List<Integer> recentTrend = analyzer.getRecentTrend(5);
        System.out.println("\n=== 最近5次恢复时间趋势 ===");
        System.out.println("恢复时间序列: " + recentTrend);
        // 预测下一次恢复时间
        double prediction = analyzer.predictNextRecovery();
        System.out.printf("预测下一次恢复时间: %.1f小时%n", prediction);
        // 额外建议输出
        System.out.println("\n=== 恢复建议 ===");
        provideRecoveryAdvice(basicStats);
    }
    // 生成模拟数据
    private static List<RunningRecord> generateMockData() {
        List<RunningRecord> records = new ArrayList<>();
        Random random = new Random(42); // 固定种子便于测试
        LocalDateTime startDate = LocalDateTime.of(2023, 1, 1, 6, 30);
        for (int i = 0; i < 30; i++) {
            // 生成随机跑步数据
            double distance = 3 + random.nextDouble() * 7; // 3-10公里
            int duration = (int)(distance * (4.5 + random.nextDouble() * 2)); // 配速4.5-6.5min/km
            int heartRate = 110 + random.nextInt(90); // 110-200
            RunningRecord record = new RunningRecord(
                startDate.plusDays(i * 2), distance, duration, heartRate
            );
            records.add(record);
        }
        return records;
    }
    // 提供恢复建议
    private static void provideRecoveryAdvice(Map<String, Object> stats) {
        double avgRecovery = (double)stats.get("avgRecoveryHours");
        if (avgRecovery <= 24) {
            System.out.println("🟢 恢复状况良好,可以维持当前训练强度");
            System.out.println("建议:适当增加训练强度,但注意逐步提升");
        } else if (avgRecovery <= 36) {
            System.out.println("🟡 恢复时间适中,注意劳逸结合");
            System.out.println("建议:合理安排跑步和休息时间,注意补充营养");
        } else if (avgRecovery <= 48) {
            System.out.println("🟠 恢复时间偏长,需要关注训练负荷");
            System.out.println("建议:适当降低训练强度,保证充足睡眠");
        } else {
            System.out.println("🔴 恢复时间过长,可能存在过度训练风险");
            System.out.println("建议:立即减少训练量,增加休息日,必要时就医咨询");
        }
        System.out.printf("平均恢复时间: %.1f小时%n", avgRecovery);
    }
}

运行示例

运行程序后,您会看到类似以下的输出(部分示例):

=== 慢跑记录列表 ===
跑步时间: 2023-01-01 06:30, 距离: 5.2km, 时长: 32分钟, 平均心率: 158, 恢复时间: 48小时, 难度: 中高强度
跑步时间: 2023-01-03 06:30, 距离: 7.8km, 时长: 45分钟, 平均心率: 142, 恢复时间: 36小时, 难度: 中等强度
...
=== 跑步统计摘要 ===
总跑步次数        : 30次
平均恢复时间      : 31.8小时
最长恢复时间      : 72小时
最短恢复时间      : 12小时
总里程           : 178.3公里
平均配速         : 5.45分钟/公里
=== 月度平均恢复时间趋势 ===
2023-01 | ██████████████ 30.2小时
2023-02 | ████████████████ 32.5小时
...
=== 难度等级分组 ===
高强度: 5次跑步
中高强度: 8次跑步
中等强度: 12次跑步
低强度: 5次跑步
=== 恢复时间分布图 ===
25-36小时    | ############ 12次
13-24小时    | ########## 9次
37-48小时    | ####### 6次
≤12小时      | ### 3次
=== 最近5次恢复时间趋势 ===
恢复时间序列: [36, 48, 24, 36, 48]
预测下一次恢复时间: 37.2小时
=== 恢复建议 ===
🟡 恢复时间适中,注意劳逸结合
建议:合理安排跑步和休息时间,注意补充营养
平均恢复时间: 31.8小时

功能说明

数据模型

  • RunningRecord 类包含完整的跑步数据
  • 自动计算恢复时间和难度等级

核心功能

  • 📊 基本统计(总次数、平均恢复时间等)
  • 📈 月度趋势分析
  • 🏷️ 难度等级分组
  • 📊 恢复时间分布图表
  • 🔮 下一次恢复时间预测(加权平均算法)

可视化输出

  • 文本柱状图
  • 月度趋势线- 恢复建议

扩展建议

您可以根据需要扩展以下功能:

  1. 数据持久化:使用JDBC连接数据库存储历史数据
  2. 更精确的算法:使用基于心率储备(Karvonen公式)的计算方式
  3. 外部数据导入:支持Garmin、Apple Watch等设备数据导入
  4. GUI界面:使用JavaFX或Swing创建图形界面
  5. 天气因素:加入温度、湿度等环境因素
  6. 营养建议:根据恢复时间提供个性化营养方案
  7. 导出功能:支持Excel、PDF等格式导出报告

这个案例提供了完整的统计分析功能,您可以根据实际需求进行调整和扩展。

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