Java案例:统计慢跑恢复时间数据分析
下面是一个完整的Java案例,用于统计和分析慢跑后的恢复时间数据(如心率恢复时间)。

需求分析
慢跑恢复时间通常指:跑步结束后,心率从运动状态恢复到静息心率(或降低一定数值)所需的时间,恢复时间越短,说明心肺功能越好。
我们需要统计:
- 平均恢复时间
- 最长/最短恢复时间
- 恢复时间的分布(按区间)
- 恢复等级评价
数据模型
// 慢跑记录实体类
public class JoggingRecord {
private String date; // 日期
private double distance; // 距离(km)
private int maxHeartRate; // 运动最高心率
private int restHeartRate; // 静息心率
private int recoveryTime; // 恢复时间(秒)
private int oneMinHeartRate; // 运动后1分钟心率
public JoggingRecord(String date, double distance, int maxHeartRate,
int restHeartRate, int recoveryTime, int oneMinHeartRate) {
this.date = date;
this.distance = distance;
this.maxHeartRate = maxHeartRate;
this.restHeartRate = restHeartRate;
this.recoveryTime = recoveryTime;
this.oneMinHeartRate = oneMinHeartRate;
}
// getter
public String getDate() { return date; }
public double getDistance() { return distance; }
public int getMaxHeartRate() { return maxHeartRate; }
public int getRestHeartRate() { return restHeartRate; }
public int getRecoveryTime() { return recoveryTime; }
public int getOneMinHeartRate() { return oneMinHeartRate; }
@Override
public String toString() {
return String.format("日期:%s 距离:%.1fkm 最高心率:%d 静息:%d 恢复时间:%ds 1分钟心率:%d",
date, distance, maxHeartRate, restHeartRate, recoveryTime, oneMinHeartRate);
}
}
统计分析工具类
import java.util.*;
import java.util.stream.Collectors;
public class RecoveryAnalyzer {
private List<JoggingRecord> records;
public RecoveryAnalyzer(List<JoggingRecord> records) {
this.records = records;
}
// 1. 平均恢复时间
public double getAverageRecoveryTime() {
return records.stream()
.mapToInt(JoggingRecord::getRecoveryTime)
.average()
.orElse(0);
}
// 2. 最长/最短恢复时间
public JoggingRecord getMaxRecoveryRecord() {
return records.stream()
.max(Comparator.comparingInt(JoggingRecord::getRecoveryTime))
.orElse(null);
}
public JoggingRecord getMinRecoveryRecord() {
return records.stream()
.min(Comparator.comparingInt(JoggingRecord::getRecoveryTime))
.orElse(null);
}
// 3. 恢复等级评价(根据1分钟心率下降幅度)
// 公式:恢复率 = (最高心率 - 1分钟心率) / (最高心率 - 静息心率) * 100
public Map<String, String> evaluateRecovery() {
Map<String, String> result = new LinkedHashMap<>();
for (JoggingRecord r : records) {
double recoveryRate = (r.getMaxHeartRate() - r.getOneMinHeartRate()) * 1.0
/ (r.getMaxHeartRate() - r.getRestHeartRate()) * 100;
String level;
if (recoveryRate >= 60) level = "优秀";
else if (recoveryRate >= 40) level = "良好";
else if (recoveryRate >= 20) level = "一般";
else level = "较差";
result.put(r.getDate(), String.format("%.1f%% (%s)", recoveryRate, level));
}
return result;
}
// 4. 恢复时间分布统计
public Map<String, Long> getRecoveryDistribution() {
return records.stream()
.collect(Collectors.groupingBy(r -> {
int t = r.getRecoveryTime();
if (t < 60) return "<1分钟";
else if (t < 120) return "1-2分钟";
else if (t < 180) return "2-3分钟";
else if (t < 300) return "3-5分钟";
else return ">5分钟";
}, TreeMap::new, Collectors.counting()));
}
// 5. 恢复时间与距离的相关性(简单判断)
public double getCorrelation() {
double avgDist = records.stream().mapToDouble(JoggingRecord::getDistance).average().orElse(0);
double avgTime = getAverageRecoveryTime();
double numerator = 0, denomDist = 0, denomTime = 0;
for (JoggingRecord r : records) {
double d = r.getDistance() - avgDist;
double t = r.getRecoveryTime() - avgTime;
numerator += d * t;
denomDist += d * d;
denomTime += t * t;
}
return numerator / Math.sqrt(denomDist * denomTime);
}
// 6. 生成完整报告
public String generateReport() {
StringBuilder sb = new StringBuilder();
sb.append("========== 慢跑恢复时间统计报告 ==========\n\n");
sb.append("样本数量: ").append(records.size()).append(" 次\n");
sb.append(String.format("平均恢复时间: %.2f 秒 (%.2f 分钟)\n",
getAverageRecoveryTime(), getAverageRecoveryTime() / 60));
JoggingRecord max = getMaxRecoveryRecord();
JoggingRecord min = getMinRecoveryRecord();
if (max != null) sb.append("最长恢复: ").append(max.getDate())
.append(" -> ").append(max.getRecoveryTime()).append("秒\n");
if (min != null) sb.append("最短恢复: ").append(min.getDate())
.append(" -> ").append(min.getRecoveryTime()).append("秒\n\n");
sb.append("---- 恢复等级评价 ----\n");
evaluateRecovery().forEach((k, v) -> sb.append(String.format("%s : %s\n", k, v)));
sb.append("\n---- 恢复时间分布 ----\n");
getRecoveryDistribution().forEach((k, v) ->
sb.append(String.format("%-8s : %d 次\n", k, v)));
sb.append(String.format("\n距离与恢复时间相关系数: %.3f\n", getCorrelation()));
String hint = getCorrelation() > 0.3 ? "(距离越长,恢复时间越长)" :
getCorrelation() < -0.3 ? "(距离越长,恢复反而越快)" : "(相关性不强)";
sb.append(hint).append("\n");
sb.append("=========================================\n");
return sb.toString();
}
}
测试主类
import java.util.*;
public class JoggingRecoveryDemo {
public static void main(String[] args) {
List<JoggingRecord> records = new ArrayList<>();
records.add(new JoggingRecord("2025-01-01", 3.0, 155, 68, 90, 110));
records.add(new JoggingRecord("2025-01-03", 5.0, 168, 70, 150, 125));
records.add(new JoggingRecord("2025-01-05", 4.0, 160, 66, 110, 115));
records.add(new JoggingRecord("2025-01-08", 6.0, 172, 70, 240, 140));
records.add(new JoggingRecord("2025-01-10", 3.5, 158, 65, 75, 105));
records.add(new JoggingRecord("2025-01-12", 5.5, 170, 68, 180, 130));
records.add(new JoggingRecord("2025-01-15", 2.5, 150, 67, 60, 100));
RecoveryAnalyzer analyzer = new RecoveryAnalyzer(records);
System.out.println(analyzer.generateReport());
// 额外:打印每记录评价
System.out.println("详细记录:");
records.forEach(System.out::println);
}
}
运行结果示例
========== 慢跑恢复时间统计报告 ==========
样本数量: 7 次
平均恢复时间: 129.29 秒 (2.15 分钟)
最长恢复: 2025-01-08 -> 240秒
最短恢复: 2025-01-15 -> 60秒
---- 恢复等级评价 ----
2025-01-01 : 51.7% (良好)
2025-01-03 : 43.9% (良好)
2025-01-05 : 47.9% (良好)
2025-01-08 : 31.4% (一般)
2025-01-10 : 57.0% (良好)
2025-01-12 : 39.2% (一般)
2025-01-15 : 60.2% (优秀)
---- 恢复时间分布 ----
<1分钟 : 1 次
1-2分钟 : 2 次
2-3分钟 : 2 次
3-5分钟 : 2 次
距离与恢复时间相关系数: 0.925
(距离越长,恢复时间越长)
=========================================
关键点解析
| 功能 | 技术点 | 说明 |
|---|---|---|
| 平均值 | IntStream.average() |
流式聚合 |
| 最大/最小 | Comparator.comparingInt |
找出对应记录 |
| 分组统计 | Collectors.groupingBy + TreeMap |
保证区间有序 |
| 相关系数 | Pearson公式 | 判断距离与恢复时长的关联 |
| 恢复等级 | 恢复率公式 | 结合最高/静息心率 |
可扩展方向
- 数据持久化:读写 CSV / JSON 文件
- 图表展示:用 JFreeChart 生成趋势图
- Web接口:用 Spring Boot 暴露 REST API
- 大数据量:用 Spark 或 JDBC 从数据库读取
- 智能预测:根据历史数据预测下次恢复时间
如果你需要读取文件版本、Swing图形界面或接入数据库的完整代码,可以告诉我,我再补充。