本文目录导读:

我来为您提供一个完整的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类包含完整的跑步数据- 自动计算恢复时间和难度等级
核心功能
- 📊 基本统计(总次数、平均恢复时间等)
- 📈 月度趋势分析
- 🏷️ 难度等级分组
- 📊 恢复时间分布图表
- 🔮 下一次恢复时间预测(加权平均算法)
可视化输出
- 文本柱状图
- 月度趋势线- 恢复建议
扩展建议
您可以根据需要扩展以下功能:
- 数据持久化:使用JDBC连接数据库存储历史数据
- 更精确的算法:使用基于心率储备(Karvonen公式)的计算方式
- 外部数据导入:支持Garmin、Apple Watch等设备数据导入
- GUI界面:使用JavaFX或Swing创建图形界面
- 天气因素:加入温度、湿度等环境因素
- 营养建议:根据恢复时间提供个性化营养方案
- 导出功能:支持Excel、PDF等格式导出报告
这个案例提供了完整的统计分析功能,您可以根据实际需求进行调整和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播